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 TEST(Buffer
, constructors
) {
53 bufferptr
ptr(buffer::create(len
));
54 EXPECT_EQ(len
, ptr
.length());
60 char* str
= new char[len
];
61 ::memset(str
, 'X', len
);
62 bufferptr
ptr(buffer::claim_char(len
, str
));
63 EXPECT_EQ(len
, ptr
.length());
64 EXPECT_EQ(str
, ptr
.c_str());
65 bufferptr clone
= ptr
.clone();
66 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
70 // buffer::create_static
73 char* str
= new char[len
];
74 bufferptr
ptr(buffer::create_static(len
, str
));
75 EXPECT_EQ(len
, ptr
.length());
76 EXPECT_EQ(str
, ptr
.c_str());
80 // buffer::create_malloc
83 bufferptr
ptr(buffer::create_malloc(len
));
84 EXPECT_EQ(len
, ptr
.length());
85 // this doesn't throw on my x86_64 wheezy box --sage
86 //EXPECT_THROW(buffer::create_malloc((unsigned)ULLONG_MAX), buffer::bad_alloc);
89 // buffer::claim_malloc
92 char* str
= (char*)malloc(len
);
93 ::memset(str
, 'X', len
);
94 bufferptr
ptr(buffer::claim_malloc(len
, str
));
95 EXPECT_EQ(len
, ptr
.length());
96 EXPECT_EQ(str
, ptr
.c_str());
97 bufferptr clone
= ptr
.clone();
98 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
104 const std::string
expected(len
, 'X');
105 bufferptr
ptr(buffer::copy(expected
.c_str(), expected
.size()));
106 EXPECT_NE(expected
.c_str(), ptr
.c_str());
107 EXPECT_EQ(0, ::memcmp(expected
.c_str(), ptr
.c_str(), len
));
110 // buffer::create_page_aligned
113 bufferptr
ptr(buffer::create_page_aligned(len
));
114 ::memset(ptr
.c_str(), 'X', len
);
115 // doesn't throw on my x86_64 wheezy box --sage
116 //EXPECT_THROW(buffer::create_page_aligned((unsigned)ULLONG_MAX), buffer::bad_alloc);
118 ASSERT_TRUE(ptr
.is_page_aligned());
120 bufferptr clone
= ptr
.clone();
121 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
125 void bench_buffer_alloc(int size
, int num
)
127 utime_t start
= ceph_clock_now();
128 for (int i
=0; i
<num
; ++i
) {
129 bufferptr p
= buffer::create(size
);
132 utime_t end
= ceph_clock_now();
133 cout
<< num
<< " alloc of size " << size
134 << " in " << (end
- start
) << std::endl
;
137 TEST(Buffer
, BenchAlloc
) {
138 bench_buffer_alloc(16384, 1000000);
139 bench_buffer_alloc(4096, 1000000);
140 bench_buffer_alloc(1024, 1000000);
141 bench_buffer_alloc(256, 1000000);
142 bench_buffer_alloc(32, 1000000);
143 bench_buffer_alloc(4, 1000000);
146 TEST(BufferRaw
, ostream
) {
148 std::ostringstream stream
;
149 stream
<< *ptr
.get_raw();
150 EXPECT_GT(stream
.str().size(), stream
.str().find("buffer::raw("));
151 EXPECT_GT(stream
.str().size(), stream
.str().find("len 1 nref 1)"));
155 // +-----------+ +-----+
157 // | offset +----------------+ |
159 // | length +---- | |
161 // +-----------+ \---+ |
163 // +-----------+ | raw |
166 TEST(BufferPtr
, constructors
) {
173 EXPECT_FALSE(ptr
.have_raw());
174 EXPECT_EQ((unsigned)0, ptr
.offset());
175 EXPECT_EQ((unsigned)0, ptr
.length());
181 bufferptr
ptr(buffer::create(len
));
182 EXPECT_TRUE(ptr
.have_raw());
183 EXPECT_EQ((unsigned)0, ptr
.offset());
184 EXPECT_EQ(len
, ptr
.length());
185 EXPECT_EQ(ptr
.raw_length(), ptr
.length());
186 EXPECT_EQ(1, ptr
.raw_nref());
189 // ptr::ptr(unsigned l)
193 EXPECT_TRUE(ptr
.have_raw());
194 EXPECT_EQ((unsigned)0, ptr
.offset());
195 EXPECT_EQ(len
, ptr
.length());
196 EXPECT_EQ(1, ptr
.raw_nref());
199 // ptr(const char *d, unsigned l)
202 const std::string
str(len
, 'X');
203 bufferptr
ptr(str
.c_str(), len
);
204 EXPECT_TRUE(ptr
.have_raw());
205 EXPECT_EQ((unsigned)0, ptr
.offset());
206 EXPECT_EQ(len
, ptr
.length());
207 EXPECT_EQ(1, ptr
.raw_nref());
208 EXPECT_EQ(0, ::memcmp(str
.c_str(), ptr
.c_str(), len
));
214 const std::string
str(len
, 'X');
215 bufferptr
original(str
.c_str(), len
);
216 bufferptr
ptr(original
);
217 EXPECT_TRUE(ptr
.have_raw());
218 EXPECT_EQ(original
.get_raw(), ptr
.get_raw());
219 EXPECT_EQ(2, ptr
.raw_nref());
220 EXPECT_EQ(0, ::memcmp(original
.c_str(), ptr
.c_str(), len
));
223 // ptr(const ptr& p, unsigned o, unsigned l)
226 const std::string
str(len
, 'X');
227 bufferptr
original(str
.c_str(), len
);
228 bufferptr
ptr(original
, 0, 0);
229 EXPECT_TRUE(ptr
.have_raw());
230 EXPECT_EQ(original
.get_raw(), ptr
.get_raw());
231 EXPECT_EQ(2, ptr
.raw_nref());
232 EXPECT_EQ(0, ::memcmp(original
.c_str(), ptr
.c_str(), len
));
233 PrCtl unset_dumpable
;
234 EXPECT_DEATH(bufferptr(original
, 0, original
.length() + 1), "");
235 EXPECT_DEATH(bufferptr(bufferptr(), 0, 0), "");
241 const std::string
str(len
, 'X');
242 bufferptr
original(str
.c_str(), len
);
243 bufferptr
ptr(std::move(original
));
244 EXPECT_TRUE(ptr
.have_raw());
245 EXPECT_FALSE(original
.have_raw());
246 EXPECT_EQ(0, ::memcmp(str
.c_str(), ptr
.c_str(), len
));
247 EXPECT_EQ(1, ptr
.raw_nref());
251 TEST(BufferPtr
, operator_assign
) {
253 // ptr& operator= (const ptr& p)
256 ptr
.copy_in(0, 3, "ABC");
259 bufferptr copy
= ptr
;
260 copy
.copy_out(1, 1, dest
);
261 ASSERT_EQ('B', dest
[0]);
265 // ptr& operator= (ptr&& p)
267 bufferptr move
= std::move(ptr
);
269 move
.copy_out(1, 1, dest
);
270 ASSERT_EQ('B', dest
[0]);
272 EXPECT_FALSE(ptr
.have_raw());
275 TEST(BufferPtr
, assignment
) {
278 // override a bufferptr set with the same raw
281 bufferptr
original(len
);
282 bufferptr
same_raw(original
.get_raw());
284 unsigned length
= len
- offset
;
285 original
.set_offset(offset
);
286 original
.set_length(length
);
288 ASSERT_EQ(2, original
.raw_nref());
289 ASSERT_EQ(same_raw
.get_raw(), original
.get_raw());
290 ASSERT_EQ(same_raw
.offset(), original
.offset());
291 ASSERT_EQ(same_raw
.length(), original
.length());
295 // self assignment is a noop
298 bufferptr
original(len
);
300 ASSERT_EQ(1, original
.raw_nref());
301 ASSERT_EQ((unsigned)0, original
.offset());
302 ASSERT_EQ(len
, original
.length());
306 // a copy points to the same raw
309 bufferptr
original(len
);
311 unsigned length
= len
- offset
;
312 original
.set_offset(offset
);
313 original
.set_length(length
);
316 ASSERT_EQ(2, original
.raw_nref());
317 ASSERT_EQ(ptr
.get_raw(), original
.get_raw());
318 ASSERT_EQ(original
.offset(), ptr
.offset());
319 ASSERT_EQ(original
.length(), ptr
.length());
323 TEST(BufferPtr
, clone
) {
326 ::memset(ptr
.c_str(), 'X', len
);
327 bufferptr clone
= ptr
.clone();
328 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
331 TEST(BufferPtr
, swap
) {
335 ::memset(ptr1
.c_str(), 'X', len
);
336 unsigned ptr1_offset
= 4;
337 ptr1
.set_offset(ptr1_offset
);
338 unsigned ptr1_length
= 3;
339 ptr1
.set_length(ptr1_length
);
342 ::memset(ptr2
.c_str(), 'Y', len
);
343 unsigned ptr2_offset
= 5;
344 ptr2
.set_offset(ptr2_offset
);
345 unsigned ptr2_length
= 7;
346 ptr2
.set_length(ptr2_length
);
350 EXPECT_EQ(ptr2_length
, ptr1
.length());
351 EXPECT_EQ(ptr2_offset
, ptr1
.offset());
352 EXPECT_EQ('Y', ptr1
[0]);
354 EXPECT_EQ(ptr1_length
, ptr2
.length());
355 EXPECT_EQ(ptr1_offset
, ptr2
.offset());
356 EXPECT_EQ('X', ptr2
[0]);
359 TEST(BufferPtr
, release
) {
364 bufferptr
ptr2(ptr1
);
365 EXPECT_EQ(2, ptr1
.raw_nref());
367 EXPECT_EQ(1, ptr1
.raw_nref());
370 TEST(BufferPtr
, have_raw
) {
373 EXPECT_FALSE(ptr
.have_raw());
377 EXPECT_TRUE(ptr
.have_raw());
381 TEST(BufferPtr
, is_n_page_sized
) {
383 bufferptr
ptr(CEPH_PAGE_SIZE
);
384 EXPECT_TRUE(ptr
.is_n_page_sized());
388 EXPECT_FALSE(ptr
.is_n_page_sized());
392 TEST(BufferPtr
, is_partial
) {
394 EXPECT_FALSE(a
.is_partial());
396 EXPECT_FALSE(b
.is_partial());
397 bufferptr
c(b
, 1, 9);
398 EXPECT_TRUE(c
.is_partial());
399 bufferptr
d(b
, 0, 9);
400 EXPECT_TRUE(d
.is_partial());
403 TEST(BufferPtr
, accessors
) {
406 ptr
.c_str()[0] = 'X';
408 const bufferptr
const_ptr(ptr
);
410 EXPECT_NE((void*)NULL
, (void*)ptr
.get_raw());
411 EXPECT_EQ('X', ptr
.c_str()[0]);
414 PrCtl unset_dumpable
;
415 EXPECT_DEATH(ptr
.c_str(), "");
416 EXPECT_DEATH(ptr
[0], "");
418 EXPECT_EQ('X', const_ptr
.c_str()[0]);
420 const bufferptr const_ptr
;
421 PrCtl unset_dumpable
;
422 EXPECT_DEATH(const_ptr
.c_str(), "");
423 EXPECT_DEATH(const_ptr
[0], "");
425 EXPECT_EQ(len
, const_ptr
.length());
426 EXPECT_EQ((unsigned)0, const_ptr
.offset());
427 EXPECT_EQ((unsigned)0, const_ptr
.start());
428 EXPECT_EQ(len
, const_ptr
.end());
429 EXPECT_EQ(len
, const_ptr
.end());
433 ptr
.set_length(ptr
.length() - unused
);
434 EXPECT_EQ(unused
, ptr
.unused_tail_length());
438 EXPECT_EQ((unsigned)0, ptr
.unused_tail_length());
441 PrCtl unset_dumpable
;
442 EXPECT_DEATH(ptr
[len
], "");
443 EXPECT_DEATH(const_ptr
[len
], "");
446 const bufferptr const_ptr
;
447 PrCtl unset_dumpable
;
448 EXPECT_DEATH(const_ptr
.raw_c_str(), "");
449 EXPECT_DEATH(const_ptr
.raw_length(), "");
450 EXPECT_DEATH(const_ptr
.raw_nref(), "");
452 EXPECT_NE((const char *)NULL
, const_ptr
.raw_c_str());
453 EXPECT_EQ(len
, const_ptr
.raw_length());
454 EXPECT_EQ(2, const_ptr
.raw_nref());
458 ptr
.set_length(ptr
.length() - wasted
* 2);
459 ptr
.set_offset(wasted
);
460 EXPECT_EQ(wasted
* 2, ptr
.wasted());
464 TEST(BufferPtr
, cmp
) {
467 bufferptr
ab("AB", 2);
468 bufferptr
af("AF", 2);
469 bufferptr
acc("ACC", 3);
470 EXPECT_GE(-1, empty
.cmp(a
));
471 EXPECT_LE(1, a
.cmp(empty
));
472 EXPECT_GE(-1, a
.cmp(ab
));
473 EXPECT_LE(1, ab
.cmp(a
));
474 EXPECT_EQ(0, ab
.cmp(ab
));
475 EXPECT_GE(-1, ab
.cmp(af
));
476 EXPECT_LE(1, af
.cmp(ab
));
477 EXPECT_GE(-1, acc
.cmp(af
));
478 EXPECT_LE(1, af
.cmp(acc
));
481 TEST(BufferPtr
, is_zero
) {
482 char str
[2] = { '\0', 'X' };
484 const bufferptr
ptr(buffer::create_static(2, str
));
485 EXPECT_FALSE(ptr
.is_zero());
488 const bufferptr
ptr(buffer::create_static(1, str
));
489 EXPECT_TRUE(ptr
.is_zero());
493 TEST(BufferPtr
, copy_out
) {
496 PrCtl unset_dumpable
;
497 EXPECT_DEATH(ptr
.copy_out((unsigned)0, (unsigned)0, NULL
), "");
501 const bufferptr
ptr(buffer::create_static(strlen(in
), in
));
502 EXPECT_THROW(ptr
.copy_out((unsigned)0, strlen(in
) + 1, NULL
), buffer::end_of_buffer
);
503 EXPECT_THROW(ptr
.copy_out(strlen(in
) + 1, (unsigned)0, NULL
), buffer::end_of_buffer
);
504 char out
[1] = { 'X' };
505 ptr
.copy_out((unsigned)1, (unsigned)1, out
);
506 EXPECT_EQ('B', out
[0]);
510 TEST(BufferPtr
, copy_out_bench
) {
511 for (int s
=1; s
<=8; s
*=2) {
512 utime_t start
= ceph_clock_now();
513 int buflen
= 1048576;
516 for (int i
=0; i
<count
; ++i
) {
517 bufferptr
bp(buflen
);
518 for (int64_t j
=0; j
<buflen
; j
+= s
) {
519 bp
.copy_out(j
, s
, (char *)&v
);
522 utime_t end
= ceph_clock_now();
523 cout
<< count
<< " fills of buffer len " << buflen
524 << " with " << s
<< " byte copy_out in"
525 << (end
- start
) << std::endl
;
529 TEST(BufferPtr
, copy_in
) {
532 PrCtl unset_dumpable
;
533 EXPECT_DEATH(ptr
.copy_in((unsigned)0, (unsigned)0, NULL
), "");
539 PrCtl unset_dumpable
;
540 EXPECT_DEATH(ptr
.copy_in((unsigned)0, strlen(in
) + 1, NULL
), "");
541 EXPECT_DEATH(ptr
.copy_in(strlen(in
) + 1, (unsigned)0, NULL
), "");
543 ptr
.copy_in((unsigned)0, (unsigned)2, in
);
544 EXPECT_EQ(in
[0], ptr
[0]);
545 EXPECT_EQ(in
[1], ptr
[1]);
549 TEST(BufferPtr
, copy_in_bench
) {
550 for (int s
=1; s
<=8; s
*=2) {
551 utime_t start
= ceph_clock_now();
552 int buflen
= 1048576;
554 for (int i
=0; i
<count
; ++i
) {
555 bufferptr
bp(buflen
);
556 for (int64_t j
=0; j
<buflen
; j
+= s
) {
557 bp
.copy_in(j
, s
, (char *)&j
, false);
560 utime_t end
= ceph_clock_now();
561 cout
<< count
<< " fills of buffer len " << buflen
562 << " with " << s
<< " byte copy_in in "
563 << (end
- start
) << std::endl
;
567 TEST(BufferPtr
, append
) {
570 PrCtl unset_dumpable
;
571 EXPECT_DEATH(ptr
.append('A'), "");
572 EXPECT_DEATH(ptr
.append("B", (unsigned)1), "");
577 PrCtl unset_dumpable
;
578 EXPECT_DEATH(ptr
.append('A'), "");
579 EXPECT_DEATH(ptr
.append("B", (unsigned)1), "");
583 EXPECT_EQ((unsigned)1, ptr
.length());
584 EXPECT_EQ('A', ptr
[0]);
585 ptr
.append("B", (unsigned)1);
586 EXPECT_EQ((unsigned)2, ptr
.length());
587 EXPECT_EQ('B', ptr
[1]);
591 TEST(BufferPtr
, append_bench
) {
593 memset(src
, 0, sizeof(src
));
594 for (int s
=4; s
<=16384; s
*=4) {
595 utime_t start
= ceph_clock_now();
596 int buflen
= 1048576;
598 for (int i
=0; i
<count
; ++i
) {
599 bufferptr
bp(buflen
);
601 for (int64_t j
=0; j
<buflen
; j
+= s
) {
602 bp
.append(src
+ j
, s
);
605 utime_t end
= ceph_clock_now();
606 cout
<< count
<< " fills of buffer len " << buflen
607 << " with " << s
<< " byte appends in "
608 << (end
- start
) << std::endl
;
612 TEST(BufferPtr
, zero
) {
614 bufferptr
ptr(buffer::create_static(strlen(str
), str
));
616 PrCtl unset_dumpable
;
617 EXPECT_DEATH(ptr
.zero(ptr
.length() + 1, 0), "");
620 EXPECT_EQ('X', ptr
[0]);
621 EXPECT_EQ('\0', ptr
[1]);
622 EXPECT_EQ('X', ptr
[2]);
624 EXPECT_EQ('\0', ptr
[0]);
627 TEST(BufferPtr
, ostream
) {
630 std::ostringstream stream
;
632 EXPECT_GT(stream
.str().size(), stream
.str().find("buffer:ptr(0~0 no raw"));
636 bufferptr
ptr(buffer::create_static(strlen(str
), str
));
637 std::ostringstream stream
;
639 EXPECT_GT(stream
.str().size(), stream
.str().find("len 4 nref 1)"));
647 // +----------+ +-----+ | | | |
648 // | append_ >-------> >--------------------> | |
649 // | buffer | +-----+ | | | |
650 // +----------+ ptr | | | |
651 // | _len | list +-----+ | | | |
652 // +----------+ +------+ ,--->+ >-----> | |
653 // | _buffers >----> >----- +-----+ | +-----+ |
654 // +----------+ +----^-+ \ ptr | raw |
655 // | last_p | / `-->+-----+ | +-----+ |
656 // +--------+-+ / + >-----> | |
657 // | ,- ,--->+-----+ | | | |
660 // +-v--+-^--+--^+-------+ | | | |
661 // | bl | ls | p | p_off >--------------->| | |
662 // +----+----+-----+-----+ | +-----+ |
663 // | | off >------------->| raw |
664 // +---------------+-----+ | |
665 // iterator +---------+
667 TEST(BufferListIterator
, constructors
) {
672 buffer::list::iterator i
;
673 EXPECT_EQ((unsigned)0, i
.get_off());
677 // iterator(list *l, unsigned o=0)
684 bufferlist::iterator
i(&bl
);
685 EXPECT_EQ((unsigned)0, i
.get_off());
689 bufferlist::iterator
i(&bl
, 1);
691 EXPECT_EQ((unsigned)2, i
.get_remaining());
696 // iterator(list *l, unsigned o, std::list<ptr>::iterator ip, unsigned po)
697 // not tested because of http://tracker.ceph.com/issues/4101
700 // iterator(const iterator& other)
705 bufferlist::iterator
i(&bl
, 1);
706 bufferlist::iterator
j(i
);
716 // const_iterator(const iterator& other)
721 bufferlist::iterator
i(&bl
);
722 bufferlist::const_iterator
ci(i
);
723 EXPECT_EQ(0u, ci
.get_off());
728 TEST(BufferListIterator
, empty_create_append_copy
) {
729 bufferlist bl
, bl2
, bl3
, out
;
736 ASSERT_TRUE(out
.contents_equal(bl
));
739 TEST(BufferListIterator
, operator_assign
) {
742 bufferlist::iterator
i(&bl
, 1);
746 bufferlist::iterator j
;
751 TEST(BufferListIterator
, get_off
) {
754 bufferlist::iterator
i(&bl
, 1);
755 EXPECT_EQ((unsigned)1, i
.get_off());
758 TEST(BufferListIterator
, get_remaining
) {
761 bufferlist::iterator
i(&bl
, 1);
762 EXPECT_EQ((unsigned)2, i
.get_remaining());
765 TEST(BufferListIterator
, end
) {
768 bufferlist::iterator
i(&bl
);
769 EXPECT_TRUE(i
.end());
773 bufferlist::iterator
i(&bl
);
774 EXPECT_FALSE(i
.end());
778 static void bench_bufferlistiter_deref(const size_t step
,
779 const size_t bufsize
,
780 const size_t bufnum
) {
781 const std::string
buf('a', bufsize
);
784 for (size_t i
= 0; i
< bufnum
; i
++) {
785 bl
.append(ceph::bufferptr(buf
.c_str(), buf
.size()));
788 utime_t start
= ceph_clock_now();
789 bufferlist::iterator iter
= bl
.begin();
790 while (iter
!= bl
.end()) {
793 utime_t end
= ceph_clock_now();
794 cout
<< bufsize
* bufnum
<< " derefs over bl with " << bufnum
795 << " buffers, each " << bufsize
<< " bytes long"
796 << " in " << (end
- start
) << std::endl
;
799 TEST(BufferListIterator
, BenchDeref
) {
800 bench_bufferlistiter_deref(1, 1, 4096000);
801 bench_bufferlistiter_deref(1, 10, 409600);
802 bench_bufferlistiter_deref(1, 100, 40960);
803 bench_bufferlistiter_deref(1, 1000, 4096);
805 bench_bufferlistiter_deref(4, 1, 1024000);
806 bench_bufferlistiter_deref(4, 10, 102400);
807 bench_bufferlistiter_deref(4, 100, 10240);
808 bench_bufferlistiter_deref(4, 1000, 1024);
811 TEST(BufferListIterator
, advance
) {
813 const std::string
one("ABC");
814 bl
.append(bufferptr(one
.c_str(), one
.size()));
815 const std::string
two("DEF");
816 bl
.append(bufferptr(two
.c_str(), two
.size()));
819 bufferlist::iterator
i(&bl
);
820 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
823 bufferlist::iterator
i(&bl
);
832 TEST(BufferListIterator
, iterate_with_empties
) {
834 EXPECT_EQ(bl
.get_num_buffers(), 0u);
836 bl
.push_back(ceph::buffer::create(0));
837 EXPECT_EQ(bl
.length(), 0u);
838 EXPECT_EQ(bl
.get_num_buffers(), 1u);
841 EXPECT_EQ(bl
.get_num_buffers(), 2u);
843 bl
.push_back(ceph::buffer::create(0));
844 EXPECT_EQ(bl
.get_num_buffers(), 3u);
846 // append bufferlist with single, 0-sized ptr inside
848 ceph::bufferlist bl_with_empty_ptr
;
849 bl_with_empty_ptr
.push_back(ceph::buffer::create(0));
850 EXPECT_EQ(bl_with_empty_ptr
.length(), 0u);
851 EXPECT_EQ(bl_with_empty_ptr
.get_num_buffers(), 1u);
853 bl
.append(bl_with_empty_ptr
);
857 EXPECT_EQ(bl
.get_num_buffers(), 5u);
859 auto i
= bl
.cbegin();
868 i
.seek(sizeof(long));
871 EXPECT_TRUE(i
== bl
.end());
876 EXPECT_FALSE(i
== bl
.end());
879 TEST(BufferListIterator
, get_ptr_and_advance
)
881 bufferptr
a("one", 3);
882 bufferptr
b("two", 3);
883 bufferptr
c("three", 5);
889 bufferlist::iterator p
= bl
.begin();
890 ASSERT_EQ(3u, p
.get_ptr_and_advance(11u, &ptr
));
891 ASSERT_EQ(bl
.length() - 3u, p
.get_remaining());
892 ASSERT_EQ(0, memcmp(ptr
, "one", 3));
893 ASSERT_EQ(2u, p
.get_ptr_and_advance(2u, &ptr
));
894 ASSERT_EQ(0, memcmp(ptr
, "tw", 2));
895 ASSERT_EQ(1u, p
.get_ptr_and_advance(4u, &ptr
));
896 ASSERT_EQ(0, memcmp(ptr
, "o", 1));
897 ASSERT_EQ(5u, p
.get_ptr_and_advance(5u, &ptr
));
898 ASSERT_EQ(0, memcmp(ptr
, "three", 5));
899 ASSERT_EQ(0u, p
.get_remaining());
902 TEST(BufferListIterator
, iterator_crc32c
) {
917 bufferlist::iterator it
= bl2
.begin();
918 ASSERT_EQ(bl1
.crc32c(0), it
.crc32c(it
.get_remaining(), 0));
919 ASSERT_EQ(0u, it
.get_remaining());
922 ASSERT_EQ(bl2
.crc32c(0), it
.crc32c(it
.get_remaining(), 0));
924 bl3
.append(s
.substr(98, 55));
927 ASSERT_EQ(bl3
.crc32c(0), it
.crc32c(55, 0));
928 ASSERT_EQ(4u, it
.get_remaining());
931 bl3
.append(s
.substr(98 + 55));
933 it
.advance(98u + 55u);
934 ASSERT_EQ(bl3
.crc32c(0), it
.crc32c(10, 0));
935 ASSERT_EQ(0u, it
.get_remaining());
938 TEST(BufferListIterator
, seek
) {
941 bufferlist::iterator
i(&bl
, 1);
947 TEST(BufferListIterator
, operator_star
) {
950 bufferlist::iterator
i(&bl
);
951 EXPECT_THROW(*i
, buffer::end_of_buffer
);
955 bufferlist::iterator
i(&bl
);
957 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
958 EXPECT_THROW(*i
, buffer::end_of_buffer
);
962 TEST(BufferListIterator
, operator_equal
) {
966 bufferlist::iterator
i(&bl
);
967 bufferlist::iterator
j(&bl
);
971 bufferlist::const_iterator ci
= bl
.begin();
972 bufferlist::iterator i
= bl
.begin();
978 TEST(BufferListIterator
, operator_nequal
) {
982 bufferlist::iterator
i(&bl
);
983 bufferlist::iterator
j(&bl
);
987 bufferlist::const_iterator ci
= bl
.begin();
988 bufferlist::const_iterator cj
= bl
.begin();
991 bufferlist::iterator i
= bl
.begin();
996 // tests begin(), end(), operator++() also
1000 EXPECT_EQ(s
[i
++], c
);
1005 TEST(BufferListIterator
, operator_plus_plus
) {
1008 bufferlist::iterator
i(&bl
);
1009 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1011 bl
.append("ABC", 3);
1013 bufferlist::iterator
i(&bl
);
1019 TEST(BufferListIterator
, get_current_ptr
) {
1022 bufferlist::iterator
i(&bl
);
1023 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1025 bl
.append("ABC", 3);
1027 bufferlist::iterator
i(&bl
, 1);
1028 const buffer::ptr ptr
= i
.get_current_ptr();
1029 EXPECT_EQ('B', ptr
[0]);
1030 EXPECT_EQ((unsigned)1, ptr
.offset());
1031 EXPECT_EQ((unsigned)2, ptr
.length());
1035 TEST(BufferListIterator
, copy
) {
1037 const char *expected
= "ABC";
1038 bl
.append(expected
, 3);
1040 // void copy(unsigned len, char *dest);
1043 char* copy
= (char*)malloc(3);
1044 ::memset(copy
, 'X', 3);
1045 bufferlist::iterator
i(&bl
);
1047 // demonstrates that it seeks back to offset if p == ls->end()
1049 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
1051 EXPECT_EQ(0, ::memcmp(copy
, expected
, 2));
1052 EXPECT_EQ('X', copy
[2]);
1055 EXPECT_EQ(0, ::memcmp(copy
, expected
, 3));
1059 // void buffer::list::iterator::copy_deep(unsigned len, ptr &dest)
1063 bufferlist::iterator
i(&bl
);
1064 i
.copy_deep(2, ptr
);
1065 EXPECT_EQ((unsigned)2, ptr
.length());
1066 EXPECT_EQ('A', ptr
[0]);
1067 EXPECT_EQ('B', ptr
[1]);
1070 // void buffer::list::iterator::copy_shallow(unsigned len, ptr &dest)
1074 bufferlist::iterator
i(&bl
);
1075 i
.copy_shallow(2, ptr
);
1076 EXPECT_EQ((unsigned)2, ptr
.length());
1077 EXPECT_EQ('A', ptr
[0]);
1078 EXPECT_EQ('B', ptr
[1]);
1081 // void buffer::list::iterator::copy(unsigned len, list &dest)
1085 bufferlist::iterator
i(&bl
);
1087 // demonstrates that it seeks back to offset if p == ls->end()
1089 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
1091 EXPECT_EQ(0, ::memcmp(copy
.c_str(), expected
, 2));
1094 EXPECT_EQ('A', copy
[0]);
1095 EXPECT_EQ('B', copy
[1]);
1096 EXPECT_EQ('A', copy
[2]);
1097 EXPECT_EQ('B', copy
[3]);
1098 EXPECT_EQ('C', copy
[4]);
1099 EXPECT_EQ((unsigned)(2 + 3), copy
.length());
1102 // void buffer::list::iterator::copy_all(list &dest)
1106 bufferlist::iterator
i(&bl
);
1108 // demonstrates that it seeks back to offset if p == ls->end()
1110 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
1112 EXPECT_EQ('A', copy
[0]);
1113 EXPECT_EQ('B', copy
[1]);
1114 EXPECT_EQ('C', copy
[2]);
1115 EXPECT_EQ((unsigned)3, copy
.length());
1118 // void copy(unsigned len, std::string &dest)
1122 bufferlist::iterator
i(&bl
);
1124 // demonstrates that it seeks back to offset if p == ls->end()
1126 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
1128 EXPECT_EQ(0, ::memcmp(copy
.c_str(), expected
, 2));
1131 EXPECT_EQ('A', copy
[0]);
1132 EXPECT_EQ('B', copy
[1]);
1133 EXPECT_EQ('A', copy
[2]);
1134 EXPECT_EQ('B', copy
[3]);
1135 EXPECT_EQ('C', copy
[4]);
1136 EXPECT_EQ((unsigned)(2 + 3), copy
.length());
1140 TEST(BufferListIterator
, copy_in
) {
1142 const char *existing
= "XXX";
1143 bl
.append(existing
, 3);
1145 // void buffer::list::iterator::copy_in(unsigned len, const char *src)
1148 bufferlist::iterator
i(&bl
);
1150 // demonstrates that it seeks back to offset if p == ls->end()
1152 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
1153 const char *expected
= "ABC";
1154 i
.copy_in(3, expected
);
1155 EXPECT_EQ(0, ::memcmp(bl
.c_str(), expected
, 3));
1156 EXPECT_EQ('A', bl
[0]);
1157 EXPECT_EQ('B', bl
[1]);
1158 EXPECT_EQ('C', bl
[2]);
1159 EXPECT_EQ((unsigned)3, bl
.length());
1162 // void buffer::list::iterator::copy_in(unsigned len, const list& otherl)
1165 bufferlist::iterator
i(&bl
);
1167 // demonstrates that it seeks back to offset if p == ls->end()
1169 EXPECT_THROW(i
.advance(200u), buffer::end_of_buffer
);
1170 bufferlist expected
;
1171 expected
.append("ABC", 3);
1172 i
.copy_in(3, expected
);
1173 EXPECT_EQ(0, ::memcmp(bl
.c_str(), expected
.c_str(), 3));
1174 EXPECT_EQ('A', bl
[0]);
1175 EXPECT_EQ('B', bl
[1]);
1176 EXPECT_EQ('C', bl
[2]);
1177 EXPECT_EQ((unsigned)3, bl
.length());
1181 // iterator& buffer::list::const_iterator::operator++()
1182 TEST(BufferListConstIterator
, operator_plus_plus
) {
1185 bufferlist::const_iterator
i(&bl
);
1186 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1188 bl
.append("ABC", 3);
1190 const bufferlist
const_bl(bl
);
1191 bufferlist::const_iterator
i(const_bl
.begin());
1198 TEST(BufferList
, constructors
) {
1204 ASSERT_EQ((unsigned)0, bl
.length());
1207 // list(unsigned prealloc)
1211 ASSERT_EQ((unsigned)0, bl
.length());
1213 ASSERT_EQ('A', bl
[0]);
1216 // list(const list& other)
1221 ASSERT_EQ('A', bl
[0]);
1222 bufferlist
copy(bl
);
1223 ASSERT_EQ('A', copy
[0]);
1226 // list(list&& other)
1231 bufferlist copy
= std::move(bl
);
1232 ASSERT_EQ(0U, bl
.length());
1233 ASSERT_EQ(1U, copy
.length());
1234 ASSERT_EQ('A', copy
[0]);
1238 void bench_bufferlist_alloc(int size
, int num
, int per
)
1240 utime_t start
= ceph_clock_now();
1241 for (int i
=0; i
<num
; ++i
) {
1243 for (int j
=0; j
<per
; ++j
)
1244 bl
.push_back(buffer::ptr_node::create(buffer::create(size
)));
1246 utime_t end
= ceph_clock_now();
1247 cout
<< num
<< " alloc of size " << size
1248 << " in " << (end
- start
) << std::endl
;
1251 TEST(BufferList
, BenchAlloc
) {
1252 bench_bufferlist_alloc(32768, 100000, 16);
1253 bench_bufferlist_alloc(25000, 100000, 16);
1254 bench_bufferlist_alloc(16384, 100000, 16);
1255 bench_bufferlist_alloc(10000, 100000, 16);
1256 bench_bufferlist_alloc(8192, 100000, 16);
1257 bench_bufferlist_alloc(6000, 100000, 16);
1258 bench_bufferlist_alloc(4096, 100000, 16);
1259 bench_bufferlist_alloc(1024, 100000, 16);
1260 bench_bufferlist_alloc(256, 100000, 16);
1261 bench_bufferlist_alloc(32, 100000, 16);
1262 bench_bufferlist_alloc(4, 100000, 16);
1265 TEST(BufferList
, append_bench_with_size_hint
) {
1266 std::array
<char, 1048576> src
= { 0, };
1268 for (size_t step
= 4; step
<= 16384; step
*= 4) {
1269 const utime_t start
= ceph_clock_now();
1271 constexpr size_t rounds
= 4000;
1272 for (size_t r
= 0; r
< rounds
; ++r
) {
1273 ceph::bufferlist
bl(std::size(src
));
1274 for (auto iter
= std::begin(src
);
1275 iter
!= std::end(src
);
1276 iter
= std::next(iter
, step
)) {
1277 bl
.append(&*iter
, step
);
1280 cout
<< rounds
<< " fills of buffer len " << src
.size()
1281 << " with " << step
<< " byte appends in "
1282 << (ceph_clock_now() - start
) << std::endl
;
1286 TEST(BufferList
, append_bench
) {
1287 std::array
<char, 1048576> src
= { 0, };
1289 for (size_t step
= 4; step
<= 16384; step
*= 4) {
1290 const utime_t start
= ceph_clock_now();
1292 constexpr size_t rounds
= 4000;
1293 for (size_t r
= 0; r
< rounds
; ++r
) {
1294 ceph::bufferlist bl
;
1295 for (auto iter
= std::begin(src
);
1296 iter
!= std::end(src
);
1297 iter
= std::next(iter
, step
)) {
1298 bl
.append(&*iter
, step
);
1301 cout
<< rounds
<< " fills of buffer len " << src
.size()
1302 << " with " << step
<< " byte appends in "
1303 << (ceph_clock_now() - start
) << std::endl
;
1307 TEST(BufferList
, operator_equal
) {
1309 // list& operator= (const list& other)
1312 bl
.append("ABC", 3);
1315 bl
.copy(1, 1, dest
);
1316 ASSERT_EQ('B', dest
[0]);
1319 bufferlist copy
= bl
;
1321 copy
.copy(1, 1, dest
);
1322 ASSERT_EQ('B', dest
[0]);
1326 // list& operator= (list&& other)
1328 bufferlist move
= std::move(bl
);
1331 move
.copy(1, 1, dest
);
1332 ASSERT_EQ('B', dest
[0]);
1334 EXPECT_TRUE(move
.length());
1335 EXPECT_TRUE(!bl
.length());
1338 TEST(BufferList
, buffers
) {
1340 ASSERT_EQ((unsigned)0, bl
.get_num_buffers());
1342 ASSERT_EQ((unsigned)1, bl
.get_num_buffers());
1345 TEST(BufferList
, to_str
) {
1349 ASSERT_EQ(bl
.to_str(), string("foo"));
1352 bufferptr
a("foobarbaz", 9);
1353 bufferptr
b("123456789", 9);
1354 bufferptr
c("ABCDEFGHI", 9);
1359 ASSERT_EQ(bl
.to_str(), string("foobarbaz123456789ABCDEFGHI"));
1363 TEST(BufferList
, swap
) {
1374 ASSERT_EQ('B', s1
[0]);
1378 ASSERT_EQ('A', s2
[0]);
1381 TEST(BufferList
, length
) {
1383 ASSERT_EQ((unsigned)0, bl
.length());
1385 ASSERT_EQ((unsigned)1, bl
.length());
1388 TEST(BufferList
, contents_equal
) {
1397 ASSERT_FALSE(bl1
.contents_equal(bl2
)); // different length
1400 ASSERT_TRUE(bl1
.contents_equal(bl2
)); // same length same content
1406 ASSERT_FALSE(bl1
.contents_equal(bl3
)); // same length different content
1409 TEST(BufferList
, is_aligned
) {
1410 const int SIMD_ALIGN
= 32;
1413 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1417 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1421 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1422 bl
.rebuild_aligned(SIMD_ALIGN
);
1423 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1427 bufferptr
ptr(buffer::create_aligned(SIMD_ALIGN
+ 1, SIMD_ALIGN
));
1429 ptr
.set_length(SIMD_ALIGN
);
1431 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1432 bl
.rebuild_aligned(SIMD_ALIGN
);
1433 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1437 TEST(BufferList
, is_n_align_sized
) {
1438 const int SIMD_ALIGN
= 32;
1441 EXPECT_TRUE(bl
.is_n_align_sized(SIMD_ALIGN
));
1446 EXPECT_FALSE(bl
.is_n_align_sized(SIMD_ALIGN
));
1450 bl
.append_zero(SIMD_ALIGN
);
1451 EXPECT_TRUE(bl
.is_n_align_sized(SIMD_ALIGN
));
1455 TEST(BufferList
, is_page_aligned
) {
1458 EXPECT_TRUE(bl
.is_page_aligned());
1462 bufferptr
ptr(buffer::create_page_aligned(2));
1466 EXPECT_FALSE(bl
.is_page_aligned());
1467 bl
.rebuild_page_aligned();
1468 EXPECT_TRUE(bl
.is_page_aligned());
1472 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1474 ptr
.set_length(CEPH_PAGE_SIZE
);
1476 EXPECT_FALSE(bl
.is_page_aligned());
1477 bl
.rebuild_page_aligned();
1478 EXPECT_TRUE(bl
.is_page_aligned());
1482 TEST(BufferList
, is_n_page_sized
) {
1485 EXPECT_TRUE(bl
.is_n_page_sized());
1490 EXPECT_FALSE(bl
.is_n_page_sized());
1494 bl
.append_zero(CEPH_PAGE_SIZE
);
1495 EXPECT_TRUE(bl
.is_n_page_sized());
1499 TEST(BufferList
, page_aligned_appender
) {
1501 auto a
= bl
.get_page_aligned_appender(5);
1502 a
.append("asdf", 4);
1504 cout
<< bl
<< std::endl
;
1505 ASSERT_EQ(1u, bl
.get_num_buffers());
1506 a
.append("asdf", 4);
1507 for (unsigned n
= 0; n
< 3 * CEPH_PAGE_SIZE
; ++n
) {
1511 cout
<< bl
<< std::endl
;
1512 ASSERT_EQ(1u, bl
.get_num_buffers());
1513 for (unsigned n
= 0; n
< 3 * CEPH_PAGE_SIZE
; ++n
) {
1517 cout
<< bl
<< std::endl
;
1518 ASSERT_EQ(2u, bl
.get_num_buffers());
1519 for (unsigned n
= 0; n
< 10 * CEPH_PAGE_SIZE
; ++n
) {
1520 a
.append("asdfasdfasdf", 1);
1523 cout
<< bl
<< std::endl
;
1526 TEST(BufferList
, rebuild_aligned_size_and_memory
) {
1527 const unsigned SIMD_ALIGN
= 32;
1528 const unsigned BUFFER_SIZE
= 67;
1531 // These two must be concatenated into one memory + size aligned
1534 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1540 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
- 1, SIMD_ALIGN
));
1543 // This one must be left alone
1545 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
, SIMD_ALIGN
));
1548 // These two must be concatenated into one memory + size aligned
1551 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1557 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
- 1, SIMD_ALIGN
));
1560 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1561 EXPECT_FALSE(bl
.is_n_align_sized(BUFFER_SIZE
));
1562 EXPECT_EQ(BUFFER_SIZE
* 3, bl
.length());
1563 EXPECT_FALSE(bl
.front().is_aligned(SIMD_ALIGN
));
1564 EXPECT_FALSE(bl
.front().is_n_align_sized(BUFFER_SIZE
));
1565 EXPECT_EQ(5U, bl
.get_num_buffers());
1566 bl
.rebuild_aligned_size_and_memory(BUFFER_SIZE
, SIMD_ALIGN
);
1567 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1568 EXPECT_TRUE(bl
.is_n_align_sized(BUFFER_SIZE
));
1569 EXPECT_EQ(3U, bl
.get_num_buffers());
1572 TEST(BufferList
, is_zero
) {
1575 EXPECT_TRUE(bl
.is_zero());
1580 EXPECT_FALSE(bl
.is_zero());
1585 EXPECT_TRUE(bl
.is_zero());
1588 for (size_t i
= 1; i
<= 256; ++i
) {
1591 EXPECT_TRUE(bl
.is_zero());
1593 // ensure buffer is a single, contiguous before testing
1595 EXPECT_FALSE(bl
.is_zero());
1600 TEST(BufferList
, clear
) {
1603 bl
.append_zero(len
);
1605 EXPECT_EQ((unsigned)0, bl
.length());
1606 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1609 TEST(BufferList
, push_back
) {
1611 // void push_back(ptr& bp)
1617 EXPECT_EQ((unsigned)0, bl
.length());
1618 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1625 ptr
.c_str()[0] = 'B';
1627 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1628 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1629 EXPECT_EQ('B', bl
.back()[0]);
1630 EXPECT_EQ(ptr
.get_raw(), bl
.back().get_raw());
1633 // void push_back(raw *r)
1639 ptr
.c_str()[0] = 'B';
1640 bl
.push_back(ptr
.get_raw());
1641 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1642 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1643 EXPECT_EQ('B', bl
.back()[0]);
1644 EXPECT_EQ(ptr
.get_raw(), bl
.back().get_raw());
1647 // void push_back(ptr&& bp)
1652 bl
.push_back(std::move(ptr
));
1653 EXPECT_EQ((unsigned)0, bl
.length());
1654 EXPECT_EQ((unsigned)0, bl
.buffers().size());
1660 ptr
.c_str()[0] = 'B';
1661 bl
.push_back(std::move(ptr
));
1662 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1663 EXPECT_EQ((unsigned)2, bl
.buffers().size());
1664 EXPECT_EQ('B', bl
.buffers().back()[0]);
1665 EXPECT_FALSE(ptr
.get_raw());
1669 TEST(BufferList
, is_contiguous
) {
1671 EXPECT_TRUE(bl
.is_contiguous());
1672 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1674 EXPECT_TRUE(bl
.is_contiguous());
1675 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1678 EXPECT_FALSE(bl
.is_contiguous());
1679 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1682 TEST(BufferList
, rebuild
) {
1685 bufferptr
ptr(buffer::create_page_aligned(2));
1691 EXPECT_FALSE(bl
.is_page_aligned());
1693 EXPECT_EQ(1U, bl
.length());
1694 EXPECT_EQ('Y', *bl
.begin());
1698 const std::string
str(CEPH_PAGE_SIZE
, 'X');
1699 bl
.append(str
.c_str(), str
.size());
1700 bl
.append(str
.c_str(), str
.size());
1701 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1702 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1704 EXPECT_TRUE(bl
.is_page_aligned());
1705 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1714 EXPECT_EQ((unsigned)1, bl
.length());
1715 bufferlist::iterator p
= bl
.begin();
1718 EXPECT_EQ(0, memcmp(dst
, "X", 1));
1722 TEST(BufferList
, rebuild_page_aligned
) {
1726 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1728 ptr
.set_length(CEPH_PAGE_SIZE
);
1731 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1732 EXPECT_FALSE(bl
.is_page_aligned());
1733 bl
.rebuild_page_aligned();
1734 EXPECT_TRUE(bl
.is_page_aligned());
1735 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1739 bufferptr
ptr(buffer::create_page_aligned(1));
1740 char *p
= ptr
.c_str();
1742 bl
.rebuild_page_aligned();
1743 EXPECT_EQ(p
, bl
.front().c_str());
1748 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
));
1749 EXPECT_TRUE(ptr
.is_page_aligned());
1750 EXPECT_TRUE(ptr
.is_n_page_sized());
1754 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1755 EXPECT_TRUE(ptr
.is_page_aligned());
1756 EXPECT_FALSE(ptr
.is_n_page_sized());
1760 bufferptr
ptr(buffer::create_page_aligned(2));
1763 EXPECT_FALSE(ptr
.is_page_aligned());
1764 EXPECT_FALSE(ptr
.is_n_page_sized());
1768 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
- 2));
1769 EXPECT_TRUE(ptr
.is_page_aligned());
1770 EXPECT_FALSE(ptr
.is_n_page_sized());
1774 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
));
1775 EXPECT_TRUE(ptr
.is_page_aligned());
1776 EXPECT_TRUE(ptr
.is_n_page_sized());
1780 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1782 ptr
.set_length(CEPH_PAGE_SIZE
);
1783 EXPECT_FALSE(ptr
.is_page_aligned());
1784 EXPECT_TRUE(ptr
.is_n_page_sized());
1787 EXPECT_EQ((unsigned)6, bl
.get_num_buffers());
1788 EXPECT_TRUE((bl
.length() & ~CEPH_PAGE_MASK
) == 0);
1789 EXPECT_FALSE(bl
.is_page_aligned());
1790 bl
.rebuild_page_aligned();
1791 EXPECT_TRUE(bl
.is_page_aligned());
1792 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
1796 TEST(BufferList
, claim
) {
1807 EXPECT_EQ((unsigned)4, to
.length());
1808 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
1810 EXPECT_EQ((unsigned)2, to
.length());
1811 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
1812 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
1813 EXPECT_EQ((unsigned)0, from
.length());
1816 TEST(BufferList
, claim_append
) {
1827 EXPECT_EQ((unsigned)4, to
.length());
1828 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
1829 to
.claim_append(from
);
1830 EXPECT_EQ((unsigned)(4 + 2), to
.length());
1831 EXPECT_EQ((unsigned)4, to
.front().length());
1832 EXPECT_EQ((unsigned)2, to
.back().length());
1833 EXPECT_EQ((unsigned)2, to
.get_num_buffers());
1834 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
1835 EXPECT_EQ((unsigned)0, from
.length());
1838 TEST(BufferList
, claim_append_piecewise
) {
1839 bufferlist bl
, t
, dst
;
1840 auto a
= bl
.get_page_aligned_appender(4);
1841 for (uint32_t i
= 0; i
< (CEPH_PAGE_SIZE
+ CEPH_PAGE_SIZE
- 1333); i
++)
1844 const char *p
= bl
.c_str();
1847 for (uint32_t i
= 0; i
< (CEPH_PAGE_SIZE
+ 1333); i
++)
1852 EXPECT_FALSE(t
.is_aligned_size_and_memory(CEPH_PAGE_SIZE
, CEPH_PAGE_SIZE
));
1853 dst
.claim_append_piecewise(t
);
1854 EXPECT_TRUE(dst
.is_aligned_size_and_memory(CEPH_PAGE_SIZE
, CEPH_PAGE_SIZE
));
1855 const char *p1
= dst
.c_str();
1856 EXPECT_TRUE(p
== p1
);
1859 TEST(BufferList
, begin
) {
1862 bufferlist::iterator i
= bl
.begin();
1866 TEST(BufferList
, end
) {
1869 bufferlist::iterator i
= bl
.end();
1871 EXPECT_EQ('C', bl
[i
.get_off()]);
1874 TEST(BufferList
, copy
) {
1876 // void copy(unsigned off, unsigned len, char *dest) const;
1880 EXPECT_THROW(bl
.copy((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer
);
1881 const char *expected
= "ABC";
1882 bl
.append(expected
);
1883 char *dest
= new char[2];
1884 bl
.copy(1, 2, dest
);
1885 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
, 2));
1889 // void copy(unsigned off, unsigned len, list &dest) const;
1894 EXPECT_THROW(bl
.copy((unsigned)100, (unsigned)100, dest
), buffer::end_of_buffer
);
1895 const char *expected
= "ABC";
1896 bl
.append(expected
);
1897 bl
.copy(1, 2, dest
);
1898 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
.c_str(), 2));
1901 // void copy(unsigned off, unsigned len, std::string &dest) const;
1906 EXPECT_THROW(bl
.copy((unsigned)100, (unsigned)100, dest
), buffer::end_of_buffer
);
1907 const char *expected
= "ABC";
1908 bl
.append(expected
);
1909 bl
.copy(1, 2, dest
);
1910 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
.c_str(), 2));
1914 TEST(BufferList
, copy_in
) {
1916 // void copy_in(unsigned off, unsigned len, const char *src);
1921 EXPECT_THROW(bl
.copy_in((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer
);
1922 bl
.copy_in(1, 2, "AB");
1923 EXPECT_EQ(0, ::memcmp("XAB", bl
.c_str(), 3));
1926 // void copy_in(unsigned off, unsigned len, const list& src);
1933 EXPECT_THROW(bl
.copy_in((unsigned)100, (unsigned)100, src
), buffer::end_of_buffer
);
1934 bl
.copy_in(1, 2, src
);
1935 EXPECT_EQ(0, ::memcmp("XAB", bl
.c_str(), 3));
1939 TEST(BufferList
, append
) {
1941 // void append(char c);
1945 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1947 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1948 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1951 // void append(const char *data, unsigned len);
1954 bufferlist
bl(CEPH_PAGE_SIZE
);
1955 std::string
str(CEPH_PAGE_SIZE
* 2, 'X');
1956 bl
.append(str
.c_str(), str
.size());
1957 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1958 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.front().length());
1959 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.back().length());
1962 // void append(const std::string& s);
1965 bufferlist
bl(CEPH_PAGE_SIZE
);
1966 std::string
str(CEPH_PAGE_SIZE
* 2, 'X');
1968 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1969 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.front().length());
1970 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.back().length());
1973 // void append(const ptr& bp);
1977 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1978 EXPECT_EQ((unsigned)0, bl
.length());
1982 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1983 EXPECT_EQ((unsigned)0, bl
.length());
1988 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1989 EXPECT_EQ((unsigned)3, bl
.length());
1993 // void append(const ptr& bp, unsigned off, unsigned len);
1998 bufferptr
back(bl
.back());
2000 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2001 EXPECT_EQ((unsigned)1, bl
.length());
2003 PrCtl unset_dumpable
;
2004 EXPECT_DEATH(bl
.append(in
, (unsigned)100, (unsigned)100), "");
2006 EXPECT_LT((unsigned)0, in
.unused_tail_length());
2008 bl
.append(in
, back
.end(), 1);
2009 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2010 EXPECT_EQ((unsigned)2, bl
.length());
2011 EXPECT_EQ('B', bl
[1]);
2015 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2016 EXPECT_EQ((unsigned)0, bl
.length());
2019 ptr
.append("AB", 2);
2020 bl
.append(ptr
, 1, 1);
2021 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2022 EXPECT_EQ((unsigned)1, bl
.length());
2025 // void append(const list& bl);
2033 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2034 EXPECT_EQ('B', bl
[1]);
2037 // void append(std::istream& in);
2041 std::string
expected("ABC\nDEF\n");
2042 std::istringstream
is("ABC\n\nDEF");
2044 EXPECT_EQ(0, ::memcmp(expected
.c_str(), bl
.c_str(), expected
.size()));
2045 EXPECT_EQ(expected
.size(), bl
.length());
2048 // void append(ptr&& bp);
2052 EXPECT_EQ((unsigned)0, bl
.buffers().size());
2053 EXPECT_EQ((unsigned)0, bl
.length());
2056 bl
.append(std::move(ptr
));
2057 EXPECT_EQ((unsigned)0, bl
.buffers().size());
2058 EXPECT_EQ((unsigned)0, bl
.length());
2062 bl
.append(std::move(ptr
));
2063 EXPECT_EQ((unsigned)1, bl
.buffers().size());
2064 EXPECT_EQ((unsigned)3, bl
.length());
2065 EXPECT_FALSE(ptr
.get_raw());
2070 TEST(BufferList
, append_hole
) {
2073 auto filler
= bl
.append_hole(1);
2074 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2075 EXPECT_EQ((unsigned)1, bl
.length());
2078 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2079 EXPECT_EQ((unsigned)3, bl
.length());
2082 filler
.copy_in((unsigned)1, &a
);
2083 EXPECT_EQ((unsigned)3, bl
.length());
2085 EXPECT_EQ(0, ::memcmp("ABC", bl
.c_str(), 3));
2091 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2092 EXPECT_EQ((unsigned)1, bl
.length());
2094 auto filler
= bl
.append_hole(1);
2095 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2096 EXPECT_EQ((unsigned)2, bl
.length());
2099 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2100 EXPECT_EQ((unsigned)3, bl
.length());
2103 filler
.copy_in((unsigned)1, &b
);
2104 EXPECT_EQ((unsigned)3, bl
.length());
2106 EXPECT_EQ(0, ::memcmp("ABC", bl
.c_str(), 3));
2110 TEST(BufferList
, append_zero
) {
2113 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2114 EXPECT_EQ((unsigned)1, bl
.length());
2116 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2117 EXPECT_EQ((unsigned)2, bl
.length());
2118 EXPECT_EQ('\0', bl
[1]);
2121 TEST(BufferList
, operator_brackets
) {
2123 EXPECT_THROW(bl
[1], buffer::end_of_buffer
);
2128 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2129 EXPECT_EQ('B', bl
[1]);
2132 TEST(BufferList
, c_str
) {
2134 EXPECT_EQ((const char*)NULL
, bl
.c_str());
2139 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2140 EXPECT_EQ(0, ::memcmp("AB", bl
.c_str(), 2));
2143 TEST(BufferList
, substr_of
) {
2145 EXPECT_THROW(bl
.substr_of(bl
, 1, 1), buffer::end_of_buffer
);
2152 for (unsigned i
= 0; i
< 4; i
++) {
2153 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2156 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2159 other
.append("TO BE CLEARED");
2160 other
.substr_of(bl
, 4, 4);
2161 EXPECT_EQ((unsigned)2, other
.get_num_buffers());
2162 EXPECT_EQ((unsigned)4, other
.length());
2163 EXPECT_EQ(0, ::memcmp("EFGH", other
.c_str(), 4));
2166 TEST(BufferList
, splice
) {
2168 EXPECT_THROW(bl
.splice(1, 1), buffer::end_of_buffer
);
2175 for (unsigned i
= 0; i
< 4; i
++) {
2176 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2179 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2184 bl
.splice(4, 4, &other
);
2185 EXPECT_EQ((unsigned)3, other
.get_num_buffers());
2186 EXPECT_EQ((unsigned)5, other
.length());
2187 EXPECT_EQ(0, ::memcmp("XEFGH", other
.c_str(), other
.length()));
2188 EXPECT_EQ((unsigned)8, bl
.length());
2191 EXPECT_EQ(0, ::memcmp("ABCDIJKL", tmp
.c_str(), tmp
.length()));
2195 EXPECT_EQ((unsigned)4, bl
.length());
2196 EXPECT_EQ(0, ::memcmp("ABCD", bl
.c_str(), bl
.length()));
2200 bufferptr
ptr1("0123456789", 10);
2202 bufferptr
ptr2("abcdefghij", 10);
2203 bl
.append(ptr2
, 5, 5);
2205 bl
.splice(10, 4, &other
);
2206 EXPECT_EQ((unsigned)11, bl
.length());
2207 EXPECT_EQ(0, ::memcmp("fghi", other
.c_str(), other
.length()));
2211 TEST(BufferList
, write
) {
2212 std::ostringstream stream
;
2215 bl
.write(1, 2, stream
);
2216 EXPECT_EQ("BC", stream
.str());
2219 TEST(BufferList
, encode_base64
) {
2223 bl
.encode_base64(other
);
2224 const char *expected
= "QUJDRA==";
2225 EXPECT_EQ(0, ::memcmp(expected
, other
.c_str(), strlen(expected
)));
2228 TEST(BufferList
, decode_base64
) {
2230 bl
.append("QUJDRA==");
2232 other
.decode_base64(bl
);
2233 const char *expected
= "ABCD";
2234 EXPECT_EQ(0, ::memcmp(expected
, other
.c_str(), strlen(expected
)));
2235 bufferlist malformed
;
2236 malformed
.append("QUJDRA");
2237 EXPECT_THROW(other
.decode_base64(malformed
), buffer::malformed_input
);
2240 TEST(BufferList
, hexdump
) {
2242 std::ostringstream stream
;
2243 bl
.append("013245678901234\0006789012345678901234", 32);
2245 EXPECT_EQ("00000000 30 31 33 32 34 35 36 37 38 39 30 31 32 33 34 00 |013245678901234.|\n"
2246 "00000010 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 |6789012345678901|\n"
2251 TEST(BufferList
, read_file
) {
2255 EXPECT_EQ(-ENOENT
, bl
.read_file("UNLIKELY", &error
));
2256 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s ; chmod 0 %s", FILENAME
, FILENAME
);
2257 EXPECT_EQ(0, ::system(cmd
));
2258 if (getuid() != 0) {
2259 EXPECT_EQ(-EACCES
, bl
.read_file(FILENAME
, &error
));
2261 snprintf(cmd
, sizeof(cmd
), "chmod +r %s", FILENAME
);
2262 EXPECT_EQ(0, ::system(cmd
));
2263 EXPECT_EQ(0, bl
.read_file(FILENAME
, &error
));
2265 EXPECT_EQ((unsigned)4, bl
.length());
2266 std::string
actual(bl
.c_str(), bl
.length());
2267 EXPECT_EQ("ABC\n", actual
);
2270 TEST(BufferList
, read_fd
) {
2273 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s", FILENAME
);
2274 EXPECT_EQ(0, ::system(cmd
));
2277 EXPECT_EQ(-EBADF
, bl
.read_fd(fd
, len
));
2278 fd
= ::open(FILENAME
, O_RDONLY
);
2280 EXPECT_EQ(len
, (unsigned)bl
.read_fd(fd
, len
));
2281 //EXPECT_EQ(CEPH_BUFFER_APPEND_SIZE - len, bl.front().unused_tail_length());
2282 EXPECT_EQ(len
, bl
.length());
2287 TEST(BufferList
, write_file
) {
2291 EXPECT_EQ(-ENOENT
, bl
.write_file("un/like/ly", mode
));
2293 EXPECT_EQ(0, bl
.write_file(FILENAME
, mode
));
2295 memset(&st
, 0, sizeof(st
));
2296 ASSERT_EQ(0, ::stat(FILENAME
, &st
));
2297 EXPECT_EQ((unsigned)(mode
| S_IFREG
), st
.st_mode
);
2301 TEST(BufferList
, write_fd
) {
2303 int fd
= ::open(FILENAME
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2306 for (unsigned i
= 0; i
< IOV_MAX
* 2; i
++) {
2307 bufferptr
ptr("A", 1);
2310 EXPECT_EQ(0, bl
.write_fd(fd
));
2313 memset(&st
, 0, sizeof(st
));
2314 ASSERT_EQ(0, ::stat(FILENAME
, &st
));
2315 EXPECT_EQ(IOV_MAX
* 2, st
.st_size
);
2319 TEST(BufferList
, write_fd_offset
) {
2321 int fd
= ::open(FILENAME
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2324 for (unsigned i
= 0; i
< IOV_MAX
* 2; i
++) {
2325 bufferptr
ptr("A", 1);
2328 uint64_t offset
= 200;
2329 EXPECT_EQ(0, bl
.write_fd(fd
, offset
));
2332 memset(&st
, 0, sizeof(st
));
2333 ASSERT_EQ(0, ::stat(FILENAME
, &st
));
2334 EXPECT_EQ(IOV_MAX
* 2 + offset
, (unsigned)st
.st_size
);
2338 TEST(BufferList
, crc32c
) {
2342 crc
= bl
.crc32c(crc
);
2343 EXPECT_EQ((unsigned)0xB3109EBF, crc
);
2344 crc
= bl
.crc32c(crc
);
2345 EXPECT_EQ((unsigned)0x5FA5C0CC, crc
);
2348 TEST(BufferList
, crc32c_append
) {
2352 for (int j
= 0; j
< 200; ++j
) {
2354 for (int i
= 0; i
< 200; ++i
) {
2359 bl
.crc32c(rand()); // mess with the cached bufferptr crc values
2362 ASSERT_EQ(bl1
.crc32c(0), bl2
.crc32c(0));
2365 TEST(BufferList
, crc32c_zeros
) {
2366 char buffer
[4*1024];
2367 for (size_t i
=0; i
< sizeof(buffer
); i
++)
2375 for (size_t j
=0; j
< 1000; j
++)
2377 bufferptr
a(buffer
, sizeof(buffer
));
2380 uint32_t crca
= bla
.crc32c(111);
2383 uint32_t crcb
= ceph_crc32c(111, (unsigned char*)blb
.c_str(), blb
.length());
2385 EXPECT_EQ(crca
, crcb
);
2389 TEST(BufferList
, crc32c_append_perf
) {
2390 int len
= 256 * 1024 * 1024;
2395 std::cout
<< "populating large buffers (a, b=c=d)" << std::endl
;
2396 char *pa
= a
.c_str();
2397 char *pb
= b
.c_str();
2398 char *pc
= c
.c_str();
2399 char *pd
= c
.c_str();
2400 for (int i
=0; i
<len
; i
++) {
2401 pa
[i
] = (i
& 0xff) ^ 73;
2402 pb
[i
] = (i
& 0xff) ^ 123;
2403 pc
[i
] = (i
& 0xff) ^ 123;
2404 pd
[i
] = (i
& 0xff) ^ 123;
2407 // track usage of cached crcs
2408 buffer::track_cached_crc(true);
2410 [[maybe_unused
]] int base_cached
= buffer::get_cached_crc();
2411 [[maybe_unused
]] int base_cached_adjusted
= buffer::get_cached_crc_adjusted();
2418 utime_t start
= ceph_clock_now();
2419 uint32_t r
= bla
.crc32c(0);
2420 utime_t end
= ceph_clock_now();
2421 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2422 std::cout
<< "a.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2423 ASSERT_EQ(r
, 1138817026u);
2425 ceph_assert(buffer::get_cached_crc() == 0 + base_cached
);
2427 utime_t start
= ceph_clock_now();
2428 uint32_t r
= bla
.crc32c(0);
2429 utime_t end
= ceph_clock_now();
2430 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2431 std::cout
<< "a.crc32c(0) (again) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2432 ASSERT_EQ(r
, 1138817026u);
2434 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2437 utime_t start
= ceph_clock_now();
2438 uint32_t r
= bla
.crc32c(5);
2439 utime_t end
= ceph_clock_now();
2440 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2441 std::cout
<< "a.crc32c(5) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2442 ASSERT_EQ(r
, 3239494520u);
2444 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2445 ceph_assert(buffer::get_cached_crc_adjusted() == 1 + base_cached_adjusted
);
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) (again) = " << 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() == 2 + base_cached_adjusted
);
2457 utime_t start
= ceph_clock_now();
2458 uint32_t r
= blb
.crc32c(0);
2459 utime_t end
= ceph_clock_now();
2460 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2461 std::cout
<< "b.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2462 ASSERT_EQ(r
, 2481791210u);
2464 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2466 utime_t start
= ceph_clock_now();
2467 uint32_t r
= blb
.crc32c(0);
2468 utime_t end
= ceph_clock_now();
2469 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2470 std::cout
<< "b.crc32c(0) (again)= " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2471 ASSERT_EQ(r
, 2481791210u);
2473 ceph_assert(buffer::get_cached_crc() == 2 + base_cached
);
2479 utime_t start
= ceph_clock_now();
2480 uint32_t r
= ab
.crc32c(0);
2481 utime_t end
= ceph_clock_now();
2482 float rate
= (float)ab
.length() / (float)(1024*1024) / (float)(end
- start
);
2483 std::cout
<< "ab.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2484 ASSERT_EQ(r
, 2988268779u);
2486 ceph_assert(buffer::get_cached_crc() == 3 + base_cached
);
2487 ceph_assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted
);
2492 utime_t start
= ceph_clock_now();
2493 uint32_t r
= ac
.crc32c(0);
2494 utime_t end
= ceph_clock_now();
2495 float rate
= (float)ac
.length() / (float)(1024*1024) / (float)(end
- start
);
2496 std::cout
<< "ac.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2497 ASSERT_EQ(r
, 2988268779u);
2499 ceph_assert(buffer::get_cached_crc() == 4 + base_cached
);
2500 ceph_assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted
);
2506 utime_t start
= ceph_clock_now();
2507 uint32_t r
= ba
.crc32c(0);
2508 utime_t end
= ceph_clock_now();
2509 float rate
= (float)ba
.length() / (float)(1024*1024) / (float)(end
- start
);
2510 std::cout
<< "ba.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2511 ASSERT_EQ(r
, 169240695u);
2513 ceph_assert(buffer::get_cached_crc() == 5 + base_cached
);
2514 ceph_assert(buffer::get_cached_crc_adjusted() == 4 + base_cached_adjusted
);
2516 utime_t start
= ceph_clock_now();
2517 uint32_t r
= ba
.crc32c(5);
2518 utime_t end
= ceph_clock_now();
2519 float rate
= (float)ba
.length() / (float)(1024*1024) / (float)(end
- start
);
2520 std::cout
<< "ba.crc32c(5) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2521 ASSERT_EQ(r
, 1265464778u);
2523 ceph_assert(buffer::get_cached_crc() == 5 + base_cached
);
2524 ceph_assert(buffer::get_cached_crc_adjusted() == 6 + base_cached_adjusted
);
2526 cout
<< "crc cache hits (same start) = " << buffer::get_cached_crc() << std::endl
;
2527 cout
<< "crc cache hits (adjusted) = " << buffer::get_cached_crc_adjusted() << std::endl
;
2530 TEST(BufferList
, compare
) {
2538 // bool operator>(bufferlist& l, bufferlist& r)
2540 ASSERT_FALSE(a
> ab
);
2541 ASSERT_TRUE(ab
> a
);
2542 ASSERT_TRUE(ac
> ab
);
2543 ASSERT_FALSE(ab
> ac
);
2544 ASSERT_FALSE(ab
> ab
);
2546 // bool operator>=(bufferlist& l, bufferlist& r)
2548 ASSERT_FALSE(a
>= ab
);
2549 ASSERT_TRUE(ab
>= a
);
2550 ASSERT_TRUE(ac
>= ab
);
2551 ASSERT_FALSE(ab
>= ac
);
2552 ASSERT_TRUE(ab
>= ab
);
2554 // bool operator<(bufferlist& l, bufferlist& r)
2556 ASSERT_TRUE(a
< ab
);
2557 ASSERT_FALSE(ab
< a
);
2558 ASSERT_FALSE(ac
< ab
);
2559 ASSERT_TRUE(ab
< ac
);
2560 ASSERT_FALSE(ab
< ab
);
2562 // bool operator<=(bufferlist& l, bufferlist& r)
2564 ASSERT_TRUE(a
<= ab
);
2565 ASSERT_FALSE(ab
<= a
);
2566 ASSERT_FALSE(ac
<= ab
);
2567 ASSERT_TRUE(ab
<= ac
);
2568 ASSERT_TRUE(ab
<= ab
);
2570 // bool operator==(bufferlist &l, bufferlist &r)
2572 ASSERT_FALSE(a
== ab
);
2573 ASSERT_FALSE(ac
== ab
);
2574 ASSERT_TRUE(ab
== ab
);
2577 TEST(BufferList
, ostream
) {
2578 std::ostringstream stream
;
2584 for (unsigned i
= 0; i
< 2; i
++) {
2585 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2589 std::cerr
<< stream
.str() << std::endl
;
2590 EXPECT_GT(stream
.str().size(), stream
.str().find("list(len=6,"));
2591 EXPECT_GT(stream
.str().size(), stream
.str().find("len 3 nref 1),\n"));
2592 EXPECT_GT(stream
.str().size(), stream
.str().find("len 3 nref 1)\n"));
2595 TEST(BufferList
, zero
) {
2602 EXPECT_EQ('A', bl
[0]);
2604 EXPECT_EQ('\0', bl
[0]);
2607 // void zero(unsigned o, unsigned l)
2617 bufferptr
ptr(s
[0], strlen(s
[0]));
2619 bl
.zero((unsigned)0, (unsigned)1);
2620 EXPECT_EQ(0, ::memcmp("\0BC", bl
.c_str(), 3));
2624 for (unsigned i
= 0; i
< 4; i
++) {
2625 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2629 PrCtl unset_dumpable
;
2630 EXPECT_DEATH(bl
.zero((unsigned)0, (unsigned)2000), "");
2632 bl
.zero((unsigned)2, (unsigned)5);
2633 EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl
.c_str(), 9));
2637 for (unsigned i
= 0; i
< 4; i
++) {
2638 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2641 bl
.zero((unsigned)3, (unsigned)3);
2642 EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl
.c_str(), 9));
2648 memset(ptr1
.c_str(), 'a', 4);
2649 memset(ptr2
.c_str(), 'b', 4);
2652 bl
.zero((unsigned)2, (unsigned)4);
2653 EXPECT_EQ(0, ::memcmp("aa\0\0\0\0bb", bl
.c_str(), 8));
2657 TEST(BufferList
, EmptyAppend
) {
2661 ASSERT_EQ(bl
.begin().end(), 1);
2664 TEST(BufferList
, InternalCarriage
) {
2665 ceph::bufferlist bl
;
2666 EXPECT_EQ(bl
.get_num_buffers(), 0u);
2669 EXPECT_EQ(bl
.get_num_buffers(), 1u);
2672 ceph::bufferlist bl_with_foo
;
2673 bl_with_foo
.append("foo", 3);
2674 EXPECT_EQ(bl_with_foo
.length(), 3u);
2675 EXPECT_EQ(bl_with_foo
.get_num_buffers(), 1u);
2677 bl
.append(bl_with_foo
);
2678 EXPECT_EQ(bl
.get_num_buffers(), 2u);
2682 EXPECT_EQ(bl
.get_num_buffers(), 3u);
2685 TEST(BufferList
, ContiguousAppender
) {
2686 ceph::bufferlist bl
;
2687 EXPECT_EQ(bl
.get_num_buffers(), 0u);
2689 // we expect a flush in ~contiguous_appender
2691 auto ap
= bl
.get_contiguous_appender(100);
2694 EXPECT_EQ(bl
.get_num_buffers(), 1u);
2696 // append bufferlist with single ptr inside. This should
2697 // commit changes to bl::_len and the underlying bp::len.
2699 ceph::bufferlist bl_with_foo
;
2700 bl_with_foo
.append("foo", 3);
2701 EXPECT_EQ(bl_with_foo
.length(), 3u);
2702 EXPECT_EQ(bl_with_foo
.get_num_buffers(), 1u);
2704 ap
.append(bl_with_foo
);
2705 // 3 as the ap::append(const bl&) splits the bp with free
2707 EXPECT_EQ(bl
.get_num_buffers(), 3u);
2711 EXPECT_EQ(bl
.get_num_buffers(), 3u);
2712 EXPECT_EQ(bl
.length(), sizeof(long) + 3u);
2714 EXPECT_EQ(bl
.length(), 2u * sizeof(long) + 3u);
2717 TEST(BufferList
, TestPtrAppend
) {
2719 char correct
[MAX_TEST
];
2721 int length
= random() % 5 > 0 ? random() % 1000 : 0;
2722 while (curpos
+ length
< MAX_TEST
) {
2727 char *current
= correct
+ curpos
;
2728 for (int i
= 0; i
< length
; ++i
) {
2729 char next
= random() % 255;
2730 correct
[curpos
++] = next
;
2732 bufferptr
ptr(current
, length
);
2735 length
= random() % 5 > 0 ? random() % 1000 : 0;
2737 ASSERT_EQ(memcmp(bl
.c_str(), correct
, curpos
), 0);
2740 TEST(BufferList
, TestDirectAppend
) {
2742 char correct
[MAX_TEST
];
2744 int length
= random() % 5 > 0 ? random() % 1000 : 0;
2745 while (curpos
+ length
< MAX_TEST
) {
2746 char *current
= correct
+ curpos
;
2747 for (int i
= 0; i
< length
; ++i
) {
2748 char next
= random() % 255;
2749 correct
[curpos
++] = next
;
2751 bl
.append(current
, length
);
2752 length
= random() % 5 > 0 ? random() % 1000 : 0;
2754 ASSERT_EQ(memcmp(bl
.c_str(), correct
, curpos
), 0);
2757 TEST(BufferList
, TestCloneNonShareable
) {
2759 std::string str
= "sharetest";
2760 bl
.append(str
.c_str(), 9);
2761 bufferlist bl_share
;
2763 bufferlist bl_noshare
;
2764 buffer::ptr unraw
= buffer::create_unshareable(10);
2765 unraw
.copy_in(0, 9, str
.c_str());
2766 bl_noshare
.append(unraw
);
2767 bufferlist bl_copied_share
= bl_share
;
2768 bufferlist bl_copied_noshare
= bl_noshare
;
2770 // assert shared bufferlist has same buffers
2771 bufferlist::iterator iter_bl
= bl
.begin();
2772 bufferlist::iterator iter_bl_share
= bl_share
.begin();
2773 // ok, this considers ptr::off, but it's still a true assertion (and below)
2774 ASSERT_TRUE(iter_bl
.get_current_ptr().c_str() ==
2775 iter_bl_share
.get_current_ptr().c_str());
2777 // assert copy of shareable bufferlist has same buffers
2778 iter_bl
= bl
.begin();
2779 bufferlist::iterator iter_bl_copied_share
= bl_copied_share
.begin();
2780 ASSERT_TRUE(iter_bl
.get_current_ptr().c_str() ==
2781 iter_bl_copied_share
.get_current_ptr().c_str());
2783 // assert copy of non-shareable bufferlist has different buffers
2784 bufferlist::iterator iter_bl_copied_noshare
= bl_copied_noshare
.begin();
2785 ASSERT_FALSE(iter_bl
.get_current_ptr().c_str() ==
2786 iter_bl_copied_noshare
.get_current_ptr().c_str());
2788 // assert that claim with CLAIM_ALLOW_NONSHAREABLE overrides safe-sharing
2789 bufferlist bl_claim_noshare_override
;
2790 void* addr
= bl_noshare
.begin().get_current_ptr().c_str();
2791 bl_claim_noshare_override
.claim(bl_noshare
,
2792 buffer::list::CLAIM_ALLOW_NONSHAREABLE
);
2793 bufferlist::iterator iter_bl_noshare_override
=
2794 bl_claim_noshare_override
.begin();
2795 ASSERT_TRUE(addr
/* the original first segment of bl_noshare() */ ==
2796 iter_bl_noshare_override
.get_current_ptr().c_str());
2799 TEST(BufferList
, TestCopyAll
) {
2800 const static size_t BIG_SZ
= 10737414;
2801 std::shared_ptr
<unsigned char> big(
2802 (unsigned char*)malloc(BIG_SZ
), free
);
2803 unsigned char c
= 0;
2804 for (size_t i
= 0; i
< BIG_SZ
; ++i
) {
2808 bl
.append((const char*)big
.get(), BIG_SZ
);
2809 bufferlist::iterator i
= bl
.begin();
2812 ASSERT_EQ(bl2
.length(), BIG_SZ
);
2813 std::shared_ptr
<unsigned char> big2(
2814 (unsigned char*)malloc(BIG_SZ
), free
);
2815 bl2
.copy(0, BIG_SZ
, (char*)big2
.get());
2816 ASSERT_EQ(memcmp(big
.get(), big2
.get(), BIG_SZ
), 0);
2819 TEST(BufferList
, InvalidateCrc
) {
2820 const static size_t buffer_size
= 262144;
2821 std::shared_ptr
<unsigned char> big(
2822 (unsigned char*)malloc(buffer_size
), free
);
2823 unsigned char c
= 0;
2824 char* ptr
= (char*) big
.get();
2826 for (size_t i
= 0; i
< buffer_size
; ++i
) {
2831 // test for crashes (shouldn't crash)
2832 bl
.invalidate_crc();
2834 // put data into bufferlist
2835 bl
.append((const char*)big
.get(), buffer_size
);
2838 __u32 crc
= bl
.crc32c(0);
2840 // modify data in bl without its knowledge
2841 inptr
= (char*) bl
.c_str();
2843 for (size_t i
= 0; i
< buffer_size
; ++i
) {
2847 // make sure data in bl are now different than in big
2848 EXPECT_NE(memcmp((void*) ptr
, (void*) inptr
, buffer_size
), 0);
2850 // crc should remain the same
2851 __u32 new_crc
= bl
.crc32c(0);
2852 EXPECT_EQ(crc
, new_crc
);
2854 // force crc invalidate, check if it is updated
2855 bl
.invalidate_crc();
2856 EXPECT_NE(crc
, bl
.crc32c(0));
2859 TEST(BufferList
, TestIsProvidedBuffer
) {
2862 bl
.push_back(buffer::create_static(100, buff
));
2863 ASSERT_TRUE(bl
.is_provided_buffer(buff
));
2864 bl
.append_zero(100);
2865 ASSERT_FALSE(bl
.is_provided_buffer(buff
));
2868 TEST(BufferList
, TestSHA1
) {
2871 sha1_digest_t sha1
= bl
.sha1();
2872 EXPECT_EQ("da39a3ee5e6b4b0d3255bfef95601890afd80709", sha1
.to_str());
2877 sha1_digest_t sha1
= bl
.sha1();
2878 EXPECT_EQ("da39a3ee5e6b4b0d3255bfef95601890afd80709", sha1
.to_str());
2883 sha1_digest_t sha1
= bl
.sha1();
2884 EXPECT_EQ("f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0", sha1
.to_str());
2889 bl2
.append(", world!");
2890 bl
.claim_append(bl2
);
2891 sha1_digest_t sha1
= bl
.sha1();
2892 EXPECT_EQ("943a702d06f34599aee1f8da8ef9f7296031d699", sha1
.to_str());
2893 bl2
.append(" How are you today?");
2894 bl
.claim_append(bl2
);
2896 EXPECT_EQ("778b5d10e5133aa28fb8de71d35b6999b9a25eb4", sha1
.to_str());
2900 memset(p
.c_str(), 0, 65536);
2903 sha1_digest_t sha1
= bl
.sha1();
2904 EXPECT_EQ("1adc95bebe9eea8c112d40cd04ab7a8d75c4f961", sha1
.to_str());
2908 TEST(BufferHash
, all
) {
2913 EXPECT_EQ((unsigned)0, hash
.digest());
2915 EXPECT_EQ((unsigned)0xB3109EBF, hash
.digest());
2917 EXPECT_EQ((unsigned)0x5FA5C0CC, hash
.digest());
2923 EXPECT_EQ((unsigned)0, hash
.digest());
2924 bufferhash
& returned_hash
= hash
<< bl
;
2925 EXPECT_EQ(&returned_hash
, &hash
);
2926 EXPECT_EQ((unsigned)0xB3109EBF, hash
.digest());
2932 * compile-command: "cd .. ; make unittest_bufferlist &&
2933 * ulimit -s unlimited ; valgrind \
2934 * --max-stackframe=20000000 --tool=memcheck \
2935 * ./unittest_bufferlist # --gtest_filter=BufferList.constructors"