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.
22 #include "include/memory.h"
27 #include "include/buffer.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"
40 #define MAX_TEST 1000000
41 #define FILENAME "bufferlist"
45 TEST(Buffer
, constructors
) {
46 bool ceph_buffer_track
= get_env_bool("CEPH_BUFFER_TRACK");
48 uint64_t history_alloc_bytes
= 0;
49 uint64_t history_alloc_num
= 0;
53 if (ceph_buffer_track
) {
54 EXPECT_EQ(0, buffer::get_total_alloc());
58 bufferptr
ptr(buffer::create(len
));
59 history_alloc_bytes
+= len
;
61 EXPECT_EQ(len
, ptr
.length());
62 if (ceph_buffer_track
) {
63 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
64 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
65 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
71 if (ceph_buffer_track
) {
72 EXPECT_EQ(0, buffer::get_total_alloc());
76 char* str
= new char[len
];
77 ::memset(str
, 'X', len
);
78 bufferptr
ptr(buffer::claim_char(len
, str
));
79 if (ceph_buffer_track
) {
80 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
81 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
82 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
84 EXPECT_EQ(len
, ptr
.length());
85 EXPECT_EQ(str
, ptr
.c_str());
86 bufferptr clone
= ptr
.clone();
87 history_alloc_bytes
+= len
;
89 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
92 // buffer::create_static
94 if (ceph_buffer_track
) {
95 EXPECT_EQ(0, buffer::get_total_alloc());
99 char* str
= new char[len
];
100 bufferptr
ptr(buffer::create_static(len
, str
));
101 if (ceph_buffer_track
) {
102 EXPECT_EQ(0, buffer::get_total_alloc());
103 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
104 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
106 EXPECT_EQ(len
, ptr
.length());
107 EXPECT_EQ(str
, ptr
.c_str());
111 // buffer::create_malloc
113 if (ceph_buffer_track
) {
114 EXPECT_EQ(0, buffer::get_total_alloc());
118 bufferptr
ptr(buffer::create_malloc(len
));
119 history_alloc_bytes
+= len
;
121 if (ceph_buffer_track
) {
122 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
123 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
124 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
126 EXPECT_EQ(len
, ptr
.length());
127 // this doesn't throw on my x86_64 wheezy box --sage
128 //EXPECT_THROW(buffer::create_malloc((unsigned)ULLONG_MAX), buffer::bad_alloc);
131 // buffer::claim_malloc
133 if (ceph_buffer_track
) {
134 EXPECT_EQ(0, buffer::get_total_alloc());
138 char* str
= (char*)malloc(len
);
139 ::memset(str
, 'X', len
);
140 bufferptr
ptr(buffer::claim_malloc(len
, str
));
141 if (ceph_buffer_track
) {
142 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
143 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
144 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
146 EXPECT_EQ(len
, ptr
.length());
147 EXPECT_EQ(str
, ptr
.c_str());
148 bufferptr clone
= ptr
.clone();
149 history_alloc_bytes
+= len
;
151 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
156 if (ceph_buffer_track
) {
157 EXPECT_EQ(0, buffer::get_total_alloc());
161 const std::string
expected(len
, 'X');
162 bufferptr
ptr(buffer::copy(expected
.c_str(), expected
.size()));
163 history_alloc_bytes
+= len
;
165 if (ceph_buffer_track
) {
166 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
167 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
168 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
170 EXPECT_NE(expected
.c_str(), ptr
.c_str());
171 EXPECT_EQ(0, ::memcmp(expected
.c_str(), ptr
.c_str(), len
));
174 // buffer::create_page_aligned
176 if (ceph_buffer_track
) {
177 EXPECT_EQ(0, buffer::get_total_alloc());
181 bufferptr
ptr(buffer::create_page_aligned(len
));
182 history_alloc_bytes
+= len
;
184 ::memset(ptr
.c_str(), 'X', len
);
185 if (ceph_buffer_track
) {
186 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
187 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
188 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
190 // doesn't throw on my x86_64 wheezy box --sage
191 //EXPECT_THROW(buffer::create_page_aligned((unsigned)ULLONG_MAX), buffer::bad_alloc);
193 ASSERT_TRUE(ptr
.is_page_aligned());
195 bufferptr clone
= ptr
.clone();
196 history_alloc_bytes
+= len
;
198 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
199 if (ceph_buffer_track
) {
200 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
201 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
204 #ifdef CEPH_HAVE_SPLICE
205 if (ceph_buffer_track
) {
206 EXPECT_EQ(0, buffer::get_total_alloc());
211 EXPECT_THROW(buffer::create_zero_copy(len
, -1, NULL
), buffer::error_code
);
212 history_alloc_bytes
+= len
;
217 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s", FILENAME
);
218 EXPECT_EQ(0, ::system(cmd
));
219 int fd
= ::open(FILENAME
, O_RDONLY
);
220 bufferptr
ptr(buffer::create_zero_copy(zc_len
, fd
, NULL
));
221 history_alloc_bytes
+= zc_len
;
223 EXPECT_EQ(zc_len
, ptr
.length());
224 if (ceph_buffer_track
) {
225 EXPECT_EQ(zc_len
, (unsigned)buffer::get_total_alloc());
226 EXPECT_EQ(history_alloc_bytes
, buffer::get_history_alloc_bytes());
227 EXPECT_EQ(history_alloc_num
, buffer::get_history_alloc_num());
233 if (ceph_buffer_track
) {
234 EXPECT_EQ(0, buffer::get_total_alloc());
238 void bench_buffer_alloc(int size
, int num
)
240 utime_t start
= ceph_clock_now();
241 for (int i
=0; i
<num
; ++i
) {
242 bufferptr p
= buffer::create(size
);
245 utime_t end
= ceph_clock_now();
246 cout
<< num
<< " alloc of size " << size
247 << " in " << (end
- start
) << std::endl
;
250 TEST(Buffer
, BenchAlloc
) {
251 bench_buffer_alloc(16384, 1000000);
252 bench_buffer_alloc(4096, 1000000);
253 bench_buffer_alloc(1024, 1000000);
254 bench_buffer_alloc(256, 1000000);
255 bench_buffer_alloc(32, 1000000);
256 bench_buffer_alloc(4, 1000000);
259 TEST(BufferRaw
, ostream
) {
261 std::ostringstream stream
;
262 stream
<< *ptr
.get_raw();
263 EXPECT_GT(stream
.str().size(), stream
.str().find("buffer::raw("));
264 EXPECT_GT(stream
.str().size(), stream
.str().find("len 1 nref 1)"));
267 #ifdef CEPH_HAVE_SPLICE
268 class TestRawPipe
: public ::testing::Test
{
270 void SetUp() override
{
273 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s", FILENAME
);
274 EXPECT_EQ(0, ::system(cmd
));
275 fd
= ::open(FILENAME
, O_RDONLY
);
278 void TearDown() override
{
286 TEST_F(TestRawPipe
, create_zero_copy
) {
287 bufferptr
ptr(buffer::create_zero_copy(len
, fd
, NULL
));
288 EXPECT_EQ(len
, ptr
.length());
289 if (get_env_bool("CEPH_BUFFER_TRACK")) {
290 EXPECT_EQ(len
, (unsigned)buffer::get_total_alloc());
294 TEST_F(TestRawPipe
, c_str_no_fd
) {
295 EXPECT_THROW(bufferptr
ptr(buffer::create_zero_copy(len
, -1, NULL
)),
299 TEST_F(TestRawPipe
, c_str_basic
) {
300 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
, fd
, NULL
));
301 EXPECT_EQ(0, memcmp(ptr
.c_str(), "ABC\n", len
));
302 EXPECT_EQ(len
, ptr
.length());
305 TEST_F(TestRawPipe
, c_str_twice
) {
306 // make sure we're creating a copy of the data and not consuming it
307 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
, fd
, NULL
));
308 EXPECT_EQ(len
, ptr
.length());
309 EXPECT_EQ(0, memcmp(ptr
.c_str(), "ABC\n", len
));
310 EXPECT_EQ(0, memcmp(ptr
.c_str(), "ABC\n", len
));
313 TEST_F(TestRawPipe
, c_str_basic_offset
) {
314 loff_t offset
= len
- 1;
315 ::lseek(fd
, offset
, SEEK_SET
);
316 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
- offset
, fd
, NULL
));
317 EXPECT_EQ(len
- offset
, ptr
.length());
318 EXPECT_EQ(0, memcmp(ptr
.c_str(), "\n", len
- offset
));
321 TEST_F(TestRawPipe
, c_str_dest_short
) {
322 ::lseek(fd
, 1, SEEK_SET
);
323 bufferptr ptr
= bufferptr(buffer::create_zero_copy(2, fd
, NULL
));
324 EXPECT_EQ(2u, ptr
.length());
325 EXPECT_EQ(0, memcmp(ptr
.c_str(), "BC", 2));
328 TEST_F(TestRawPipe
, c_str_source_short
) {
329 ::lseek(fd
, 1, SEEK_SET
);
330 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
, fd
, NULL
));
331 EXPECT_EQ(len
- 1, ptr
.length());
332 EXPECT_EQ(0, memcmp(ptr
.c_str(), "BC\n", len
- 1));
335 TEST_F(TestRawPipe
, c_str_explicit_zero_offset
) {
337 ::lseek(fd
, 1, SEEK_SET
);
338 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
, fd
, &offset
));
339 EXPECT_EQ(len
, offset
);
340 EXPECT_EQ(len
, ptr
.length());
341 EXPECT_EQ(0, memcmp(ptr
.c_str(), "ABC\n", len
));
344 TEST_F(TestRawPipe
, c_str_explicit_positive_offset
) {
346 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
- offset
, fd
,
348 EXPECT_EQ(len
, offset
);
349 EXPECT_EQ(len
- 1, ptr
.length());
350 EXPECT_EQ(0, memcmp(ptr
.c_str(), "BC\n", len
- 1));
353 TEST_F(TestRawPipe
, c_str_explicit_positive_empty_result
) {
354 int64_t offset
= len
;
355 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
- offset
, fd
,
357 EXPECT_EQ(len
, offset
);
358 EXPECT_EQ(0u, ptr
.length());
361 TEST_F(TestRawPipe
, c_str_source_short_explicit_offset
) {
363 bufferptr ptr
= bufferptr(buffer::create_zero_copy(len
, fd
, &offset
));
364 EXPECT_EQ(len
, offset
);
365 EXPECT_EQ(len
- 1, ptr
.length());
366 EXPECT_EQ(0, memcmp(ptr
.c_str(), "BC\n", len
- 1));
369 TEST_F(TestRawPipe
, c_str_dest_short_explicit_offset
) {
371 bufferptr ptr
= bufferptr(buffer::create_zero_copy(2, fd
, &offset
));
372 EXPECT_EQ(3, offset
);
373 EXPECT_EQ(2u, ptr
.length());
374 EXPECT_EQ(0, memcmp(ptr
.c_str(), "BC", 2));
377 TEST_F(TestRawPipe
, buffer_list_read_fd_zero_copy
) {
379 EXPECT_EQ(-EBADF
, bl
.read_fd_zero_copy(-1, len
));
381 EXPECT_EQ(0, bl
.read_fd_zero_copy(fd
, len
));
382 EXPECT_EQ(len
, bl
.length());
383 EXPECT_EQ(0u, bl
.front().unused_tail_length());
384 EXPECT_EQ(1u, bl
.get_num_buffers());
385 EXPECT_EQ(len
, bl
.front().raw_length());
386 EXPECT_EQ(0, memcmp(bl
.c_str(), "ABC\n", len
));
387 EXPECT_TRUE(bl
.can_zero_copy());
390 TEST_F(TestRawPipe
, buffer_list_write_fd_zero_copy
) {
393 EXPECT_EQ(0, bl
.read_fd_zero_copy(fd
, len
));
394 EXPECT_TRUE(bl
.can_zero_copy());
395 int out_fd
= ::open(FILENAME
, O_RDWR
|O_CREAT
|O_TRUNC
, 0600);
396 EXPECT_EQ(0, bl
.write_fd_zero_copy(out_fd
));
398 memset(&st
, 0, sizeof(st
));
399 EXPECT_EQ(0, ::stat(FILENAME
, &st
));
400 EXPECT_EQ(len
, st
.st_size
);
402 EXPECT_EQ((int)len
, safe_read(out_fd
, buf
, len
+ 1));
403 EXPECT_EQ(0, memcmp(buf
, "ABC\n", len
));
407 #endif // CEPH_HAVE_SPLICE
410 // +-----------+ +-----+
412 // | offset +----------------+ |
414 // | length +---- | |
416 // +-----------+ \---+ |
418 // +-----------+ | raw |
421 TEST(BufferPtr
, constructors
) {
428 EXPECT_FALSE(ptr
.have_raw());
429 EXPECT_EQ((unsigned)0, ptr
.offset());
430 EXPECT_EQ((unsigned)0, ptr
.length());
436 bufferptr
ptr(buffer::create(len
));
437 EXPECT_TRUE(ptr
.have_raw());
438 EXPECT_EQ((unsigned)0, ptr
.offset());
439 EXPECT_EQ(len
, ptr
.length());
440 EXPECT_EQ(ptr
.raw_length(), ptr
.length());
441 EXPECT_EQ(1, ptr
.raw_nref());
444 // ptr::ptr(unsigned l)
448 EXPECT_TRUE(ptr
.have_raw());
449 EXPECT_EQ((unsigned)0, ptr
.offset());
450 EXPECT_EQ(len
, ptr
.length());
451 EXPECT_EQ(1, ptr
.raw_nref());
454 // ptr(const char *d, unsigned l)
457 const std::string
str(len
, 'X');
458 bufferptr
ptr(str
.c_str(), len
);
459 EXPECT_TRUE(ptr
.have_raw());
460 EXPECT_EQ((unsigned)0, ptr
.offset());
461 EXPECT_EQ(len
, ptr
.length());
462 EXPECT_EQ(1, ptr
.raw_nref());
463 EXPECT_EQ(0, ::memcmp(str
.c_str(), ptr
.c_str(), len
));
469 const std::string
str(len
, 'X');
470 bufferptr
original(str
.c_str(), len
);
471 bufferptr
ptr(original
);
472 EXPECT_TRUE(ptr
.have_raw());
473 EXPECT_EQ(original
.get_raw(), ptr
.get_raw());
474 EXPECT_EQ(2, ptr
.raw_nref());
475 EXPECT_EQ(0, ::memcmp(original
.c_str(), ptr
.c_str(), len
));
478 // ptr(const ptr& p, unsigned o, unsigned l)
481 const std::string
str(len
, 'X');
482 bufferptr
original(str
.c_str(), len
);
483 bufferptr
ptr(original
, 0, 0);
484 EXPECT_TRUE(ptr
.have_raw());
485 EXPECT_EQ(original
.get_raw(), ptr
.get_raw());
486 EXPECT_EQ(2, ptr
.raw_nref());
487 EXPECT_EQ(0, ::memcmp(original
.c_str(), ptr
.c_str(), len
));
488 PrCtl unset_dumpable
;
489 EXPECT_DEATH(bufferptr(original
, 0, original
.length() + 1), "");
490 EXPECT_DEATH(bufferptr(bufferptr(), 0, 0), "");
496 const std::string
str(len
, 'X');
497 bufferptr
original(str
.c_str(), len
);
498 bufferptr
ptr(std::move(original
));
499 EXPECT_TRUE(ptr
.have_raw());
500 EXPECT_FALSE(original
.have_raw());
501 EXPECT_EQ(0, ::memcmp(str
.c_str(), ptr
.c_str(), len
));
502 EXPECT_EQ(1, ptr
.raw_nref());
506 TEST(BufferPtr
, operator_assign
) {
508 // ptr& operator= (const ptr& p)
511 ptr
.copy_in(0, 3, "ABC");
514 bufferptr copy
= ptr
;
515 copy
.copy_out(1, 1, dest
);
516 ASSERT_EQ('B', dest
[0]);
520 // ptr& operator= (ptr&& p)
522 bufferptr move
= std::move(ptr
);
524 move
.copy_out(1, 1, dest
);
525 ASSERT_EQ('B', dest
[0]);
527 EXPECT_FALSE(ptr
.have_raw());
530 TEST(BufferPtr
, assignment
) {
533 // override a bufferptr set with the same raw
536 bufferptr
original(len
);
537 bufferptr
same_raw(original
.get_raw());
539 unsigned length
= len
- offset
;
540 original
.set_offset(offset
);
541 original
.set_length(length
);
543 ASSERT_EQ(2, original
.raw_nref());
544 ASSERT_EQ(same_raw
.get_raw(), original
.get_raw());
545 ASSERT_EQ(same_raw
.offset(), original
.offset());
546 ASSERT_EQ(same_raw
.length(), original
.length());
550 // self assignment is a noop
553 bufferptr
original(len
);
555 ASSERT_EQ(1, original
.raw_nref());
556 ASSERT_EQ((unsigned)0, original
.offset());
557 ASSERT_EQ(len
, original
.length());
561 // a copy points to the same raw
564 bufferptr
original(len
);
566 unsigned length
= len
- offset
;
567 original
.set_offset(offset
);
568 original
.set_length(length
);
571 ASSERT_EQ(2, original
.raw_nref());
572 ASSERT_EQ(ptr
.get_raw(), original
.get_raw());
573 ASSERT_EQ(original
.offset(), ptr
.offset());
574 ASSERT_EQ(original
.length(), ptr
.length());
578 TEST(BufferPtr
, clone
) {
581 ::memset(ptr
.c_str(), 'X', len
);
582 bufferptr clone
= ptr
.clone();
583 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
586 TEST(BufferPtr
, swap
) {
590 ::memset(ptr1
.c_str(), 'X', len
);
591 unsigned ptr1_offset
= 4;
592 ptr1
.set_offset(ptr1_offset
);
593 unsigned ptr1_length
= 3;
594 ptr1
.set_length(ptr1_length
);
597 ::memset(ptr2
.c_str(), 'Y', len
);
598 unsigned ptr2_offset
= 5;
599 ptr2
.set_offset(ptr2_offset
);
600 unsigned ptr2_length
= 7;
601 ptr2
.set_length(ptr2_length
);
605 EXPECT_EQ(ptr2_length
, ptr1
.length());
606 EXPECT_EQ(ptr2_offset
, ptr1
.offset());
607 EXPECT_EQ('Y', ptr1
[0]);
609 EXPECT_EQ(ptr1_length
, ptr2
.length());
610 EXPECT_EQ(ptr1_offset
, ptr2
.offset());
611 EXPECT_EQ('X', ptr2
[0]);
614 TEST(BufferPtr
, release
) {
619 bufferptr
ptr2(ptr1
);
620 EXPECT_EQ(2, ptr1
.raw_nref());
622 EXPECT_EQ(1, ptr1
.raw_nref());
625 TEST(BufferPtr
, have_raw
) {
628 EXPECT_FALSE(ptr
.have_raw());
632 EXPECT_TRUE(ptr
.have_raw());
636 TEST(BufferPtr
, at_buffer_head
) {
638 EXPECT_TRUE(ptr
.at_buffer_head());
640 EXPECT_FALSE(ptr
.at_buffer_head());
643 TEST(BufferPtr
, at_buffer_tail
) {
645 EXPECT_TRUE(ptr
.at_buffer_tail());
647 EXPECT_FALSE(ptr
.at_buffer_tail());
650 TEST(BufferPtr
, is_n_page_sized
) {
652 bufferptr
ptr(CEPH_PAGE_SIZE
);
653 EXPECT_TRUE(ptr
.is_n_page_sized());
657 EXPECT_FALSE(ptr
.is_n_page_sized());
661 TEST(BufferPtr
, is_partial
) {
663 EXPECT_FALSE(a
.is_partial());
665 EXPECT_FALSE(b
.is_partial());
666 bufferptr
c(b
, 1, 9);
667 EXPECT_TRUE(c
.is_partial());
668 bufferptr
d(b
, 0, 9);
669 EXPECT_TRUE(d
.is_partial());
672 TEST(BufferPtr
, accessors
) {
675 ptr
.c_str()[0] = 'X';
677 const bufferptr
const_ptr(ptr
);
679 EXPECT_NE((void*)NULL
, (void*)ptr
.get_raw());
680 EXPECT_EQ('X', ptr
.c_str()[0]);
683 PrCtl unset_dumpable
;
684 EXPECT_DEATH(ptr
.c_str(), "");
685 EXPECT_DEATH(ptr
[0], "");
687 EXPECT_EQ('X', const_ptr
.c_str()[0]);
689 const bufferptr const_ptr
;
690 PrCtl unset_dumpable
;
691 EXPECT_DEATH(const_ptr
.c_str(), "");
692 EXPECT_DEATH(const_ptr
[0], "");
694 EXPECT_EQ(len
, const_ptr
.length());
695 EXPECT_EQ((unsigned)0, const_ptr
.offset());
696 EXPECT_EQ((unsigned)0, const_ptr
.start());
697 EXPECT_EQ(len
, const_ptr
.end());
698 EXPECT_EQ(len
, const_ptr
.end());
702 ptr
.set_length(ptr
.length() - unused
);
703 EXPECT_EQ(unused
, ptr
.unused_tail_length());
707 EXPECT_EQ((unsigned)0, ptr
.unused_tail_length());
710 PrCtl unset_dumpable
;
711 EXPECT_DEATH(ptr
[len
], "");
712 EXPECT_DEATH(const_ptr
[len
], "");
715 const bufferptr const_ptr
;
716 PrCtl unset_dumpable
;
717 EXPECT_DEATH(const_ptr
.raw_c_str(), "");
718 EXPECT_DEATH(const_ptr
.raw_length(), "");
719 EXPECT_DEATH(const_ptr
.raw_nref(), "");
721 EXPECT_NE((const char *)NULL
, const_ptr
.raw_c_str());
722 EXPECT_EQ(len
, const_ptr
.raw_length());
723 EXPECT_EQ(2, const_ptr
.raw_nref());
727 ptr
.set_length(ptr
.length() - wasted
* 2);
728 ptr
.set_offset(wasted
);
729 EXPECT_EQ(wasted
* 2, ptr
.wasted());
733 TEST(BufferPtr
, cmp
) {
736 bufferptr
ab("AB", 2);
737 bufferptr
af("AF", 2);
738 bufferptr
acc("ACC", 3);
739 EXPECT_GE(-1, empty
.cmp(a
));
740 EXPECT_LE(1, a
.cmp(empty
));
741 EXPECT_GE(-1, a
.cmp(ab
));
742 EXPECT_LE(1, ab
.cmp(a
));
743 EXPECT_EQ(0, ab
.cmp(ab
));
744 EXPECT_GE(-1, ab
.cmp(af
));
745 EXPECT_LE(1, af
.cmp(ab
));
746 EXPECT_GE(-1, acc
.cmp(af
));
747 EXPECT_LE(1, af
.cmp(acc
));
750 TEST(BufferPtr
, is_zero
) {
751 char str
[2] = { '\0', 'X' };
753 const bufferptr
ptr(buffer::create_static(2, str
));
754 EXPECT_FALSE(ptr
.is_zero());
757 const bufferptr
ptr(buffer::create_static(1, str
));
758 EXPECT_TRUE(ptr
.is_zero());
762 TEST(BufferPtr
, copy_out
) {
765 PrCtl unset_dumpable
;
766 EXPECT_DEATH(ptr
.copy_out((unsigned)0, (unsigned)0, NULL
), "");
770 const bufferptr
ptr(buffer::create_static(strlen(in
), in
));
771 EXPECT_THROW(ptr
.copy_out((unsigned)0, strlen(in
) + 1, NULL
), buffer::end_of_buffer
);
772 EXPECT_THROW(ptr
.copy_out(strlen(in
) + 1, (unsigned)0, NULL
), buffer::end_of_buffer
);
773 char out
[1] = { 'X' };
774 ptr
.copy_out((unsigned)1, (unsigned)1, out
);
775 EXPECT_EQ('B', out
[0]);
779 TEST(BufferPtr
, copy_out_bench
) {
780 for (int s
=1; s
<=8; s
*=2) {
781 utime_t start
= ceph_clock_now();
782 int buflen
= 1048576;
785 for (int i
=0; i
<count
; ++i
) {
786 bufferptr
bp(buflen
);
787 for (int64_t j
=0; j
<buflen
; j
+= s
) {
788 bp
.copy_out(j
, s
, (char *)&v
);
791 utime_t end
= ceph_clock_now();
792 cout
<< count
<< " fills of buffer len " << buflen
793 << " with " << s
<< " byte copy_out in"
794 << (end
- start
) << std::endl
;
798 TEST(BufferPtr
, copy_in
) {
801 PrCtl unset_dumpable
;
802 EXPECT_DEATH(ptr
.copy_in((unsigned)0, (unsigned)0, NULL
), "");
808 PrCtl unset_dumpable
;
809 EXPECT_DEATH(ptr
.copy_in((unsigned)0, strlen(in
) + 1, NULL
), "");
810 EXPECT_DEATH(ptr
.copy_in(strlen(in
) + 1, (unsigned)0, NULL
), "");
812 ptr
.copy_in((unsigned)0, (unsigned)2, in
);
813 EXPECT_EQ(in
[0], ptr
[0]);
814 EXPECT_EQ(in
[1], ptr
[1]);
818 TEST(BufferPtr
, copy_in_bench
) {
819 for (int s
=1; s
<=8; s
*=2) {
820 utime_t start
= ceph_clock_now();
821 int buflen
= 1048576;
823 for (int i
=0; i
<count
; ++i
) {
824 bufferptr
bp(buflen
);
825 for (int64_t j
=0; j
<buflen
; j
+= s
) {
826 bp
.copy_in(j
, s
, (char *)&j
, false);
829 utime_t end
= ceph_clock_now();
830 cout
<< count
<< " fills of buffer len " << buflen
831 << " with " << s
<< " byte copy_in in "
832 << (end
- start
) << std::endl
;
836 TEST(BufferPtr
, append
) {
839 PrCtl unset_dumpable
;
840 EXPECT_DEATH(ptr
.append('A'), "");
841 EXPECT_DEATH(ptr
.append("B", (unsigned)1), "");
846 PrCtl unset_dumpable
;
847 EXPECT_DEATH(ptr
.append('A'), "");
848 EXPECT_DEATH(ptr
.append("B", (unsigned)1), "");
852 EXPECT_EQ((unsigned)1, ptr
.length());
853 EXPECT_EQ('A', ptr
[0]);
854 ptr
.append("B", (unsigned)1);
855 EXPECT_EQ((unsigned)2, ptr
.length());
856 EXPECT_EQ('B', ptr
[1]);
860 TEST(BufferPtr
, append_bench
) {
862 memset(src
, 0, sizeof(src
));
863 for (int s
=4; s
<=16384; s
*=4) {
864 utime_t start
= ceph_clock_now();
865 int buflen
= 1048576;
867 for (int i
=0; i
<count
; ++i
) {
868 bufferptr
bp(buflen
);
870 for (int64_t j
=0; j
<buflen
; j
+= s
) {
874 utime_t end
= ceph_clock_now();
875 cout
<< count
<< " fills of buffer len " << buflen
876 << " with " << s
<< " byte appends in "
877 << (end
- start
) << std::endl
;
881 TEST(BufferPtr
, zero
) {
883 bufferptr
ptr(buffer::create_static(strlen(str
), str
));
885 PrCtl unset_dumpable
;
886 EXPECT_DEATH(ptr
.zero(ptr
.length() + 1, 0), "");
889 EXPECT_EQ('X', ptr
[0]);
890 EXPECT_EQ('\0', ptr
[1]);
891 EXPECT_EQ('X', ptr
[2]);
893 EXPECT_EQ('\0', ptr
[0]);
896 TEST(BufferPtr
, ostream
) {
899 std::ostringstream stream
;
901 EXPECT_GT(stream
.str().size(), stream
.str().find("buffer:ptr(0~0 no raw"));
905 bufferptr
ptr(buffer::create_static(strlen(str
), str
));
906 std::ostringstream stream
;
908 EXPECT_GT(stream
.str().size(), stream
.str().find("len 4 nref 1)"));
916 // +----------+ +-----+ | | | |
917 // | append_ >-------> >--------------------> | |
918 // | buffer | +-----+ | | | |
919 // +----------+ ptr | | | |
920 // | _len | list +-----+ | | | |
921 // +----------+ +------+ ,--->+ >-----> | |
922 // | _buffers >----> >----- +-----+ | +-----+ |
923 // +----------+ +----^-+ \ ptr | raw |
924 // | last_p | / `-->+-----+ | +-----+ |
925 // +--------+-+ / + >-----> | |
926 // | ,- ,--->+-----+ | | | |
929 // +-v--+-^--+--^+-------+ | | | |
930 // | bl | ls | p | p_off >--------------->| | |
931 // +----+----+-----+-----+ | +-----+ |
932 // | | off >------------->| raw |
933 // +---------------+-----+ | |
934 // iterator +---------+
936 TEST(BufferListIterator
, constructors
) {
941 buffer::list::iterator i
;
942 EXPECT_EQ((unsigned)0, i
.get_off());
946 // iterator(list *l, unsigned o=0)
953 bufferlist::iterator
i(&bl
);
954 EXPECT_EQ((unsigned)0, i
.get_off());
958 bufferlist::iterator
i(&bl
, 1);
960 EXPECT_EQ((unsigned)2, i
.get_remaining());
965 // iterator(list *l, unsigned o, std::list<ptr>::iterator ip, unsigned po)
966 // not tested because of http://tracker.ceph.com/issues/4101
969 // iterator(const iterator& other)
974 bufferlist::iterator
i(&bl
, 1);
975 bufferlist::iterator
j(i
);
987 // const_iterator(const iterator& other)
992 bufferlist::iterator
i(&bl
);
993 bufferlist::const_iterator
ci(i
);
994 EXPECT_EQ(0u, ci
.get_off());
999 TEST(BufferListIterator
, empty_create_append_copy
) {
1000 bufferlist bl
, bl2
, bl3
, out
;
1007 ASSERT_TRUE(out
.contents_equal(bl
));
1010 TEST(BufferListIterator
, operator_assign
) {
1012 bl
.append("ABC", 3);
1013 bufferlist::iterator
i(&bl
, 1);
1017 bufferlist::iterator j
;
1022 TEST(BufferListIterator
, get_off
) {
1024 bl
.append("ABC", 3);
1025 bufferlist::iterator
i(&bl
, 1);
1026 EXPECT_EQ((unsigned)1, i
.get_off());
1029 TEST(BufferListIterator
, get_remaining
) {
1031 bl
.append("ABC", 3);
1032 bufferlist::iterator
i(&bl
, 1);
1033 EXPECT_EQ((unsigned)2, i
.get_remaining());
1036 TEST(BufferListIterator
, end
) {
1039 bufferlist::iterator
i(&bl
);
1040 EXPECT_TRUE(i
.end());
1042 bl
.append("ABC", 3);
1044 bufferlist::iterator
i(&bl
);
1045 EXPECT_FALSE(i
.end());
1049 TEST(BufferListIterator
, advance
) {
1051 const std::string
one("ABC");
1052 bl
.append(bufferptr(one
.c_str(), one
.size()));
1053 const std::string
two("DEF");
1054 bl
.append(bufferptr(two
.c_str(), two
.size()));
1057 bufferlist::iterator
i(&bl
);
1058 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1061 bufferlist::iterator
i(&bl
);
1062 EXPECT_THROW(i
.advance(-1), buffer::end_of_buffer
);
1065 bufferlist::iterator
i(&bl
);
1078 TEST(BufferListIterator
, get_ptr_and_advance
)
1080 bufferptr
a("one", 3);
1081 bufferptr
b("two", 3);
1082 bufferptr
c("three", 5);
1088 bufferlist::iterator p
= bl
.begin();
1089 ASSERT_EQ(3u, p
.get_ptr_and_advance(11, &ptr
));
1090 ASSERT_EQ(bl
.length() - 3u, p
.get_remaining());
1091 ASSERT_EQ(0, memcmp(ptr
, "one", 3));
1092 ASSERT_EQ(2u, p
.get_ptr_and_advance(2, &ptr
));
1093 ASSERT_EQ(0, memcmp(ptr
, "tw", 2));
1094 ASSERT_EQ(1u, p
.get_ptr_and_advance(4, &ptr
));
1095 ASSERT_EQ(0, memcmp(ptr
, "o", 1));
1096 ASSERT_EQ(5u, p
.get_ptr_and_advance(5, &ptr
));
1097 ASSERT_EQ(0, memcmp(ptr
, "three", 5));
1098 ASSERT_EQ(0u, p
.get_remaining());
1101 TEST(BufferListIterator
, iterator_crc32c
) {
1106 string
s1(100, 'a');
1116 bufferlist::iterator it
= bl2
.begin();
1117 ASSERT_EQ(bl1
.crc32c(0), it
.crc32c(it
.get_remaining(), 0));
1118 ASSERT_EQ(0u, it
.get_remaining());
1121 ASSERT_EQ(bl2
.crc32c(0), it
.crc32c(it
.get_remaining(), 0));
1123 bl3
.append(s
.substr(98, 55));
1126 ASSERT_EQ(bl3
.crc32c(0), it
.crc32c(55, 0));
1127 ASSERT_EQ(4u, it
.get_remaining());
1130 bl3
.append(s
.substr(98 + 55));
1132 it
.advance(98 + 55);
1133 ASSERT_EQ(bl3
.crc32c(0), it
.crc32c(10, 0));
1134 ASSERT_EQ(0u, it
.get_remaining());
1137 TEST(BufferListIterator
, seek
) {
1139 bl
.append("ABC", 3);
1140 bufferlist::iterator
i(&bl
, 1);
1146 TEST(BufferListIterator
, operator_star
) {
1149 bufferlist::iterator
i(&bl
);
1150 EXPECT_THROW(*i
, buffer::end_of_buffer
);
1152 bl
.append("ABC", 3);
1154 bufferlist::iterator
i(&bl
);
1156 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1157 EXPECT_THROW(*i
, buffer::end_of_buffer
);
1161 TEST(BufferListIterator
, operator_equal
) {
1163 bl
.append("ABC", 3);
1165 bufferlist::iterator
i(&bl
);
1166 bufferlist::iterator
j(&bl
);
1170 bufferlist::const_iterator ci
= bl
.begin();
1171 bufferlist::iterator i
= bl
.begin();
1177 TEST(BufferListIterator
, operator_nequal
) {
1179 bl
.append("ABC", 3);
1181 bufferlist::iterator
i(&bl
);
1182 bufferlist::iterator
j(&bl
);
1186 bufferlist::const_iterator ci
= bl
.begin();
1187 bufferlist::const_iterator cj
= bl
.begin();
1190 bufferlist::iterator i
= bl
.begin();
1195 // tests begin(), end(), operator++() also
1199 EXPECT_EQ(s
[i
++], c
);
1204 TEST(BufferListIterator
, operator_plus_plus
) {
1207 bufferlist::iterator
i(&bl
);
1208 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1210 bl
.append("ABC", 3);
1212 bufferlist::iterator
i(&bl
);
1218 TEST(BufferListIterator
, get_current_ptr
) {
1221 bufferlist::iterator
i(&bl
);
1222 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1224 bl
.append("ABC", 3);
1226 bufferlist::iterator
i(&bl
, 1);
1227 const buffer::ptr ptr
= i
.get_current_ptr();
1228 EXPECT_EQ('B', ptr
[0]);
1229 EXPECT_EQ((unsigned)1, ptr
.offset());
1230 EXPECT_EQ((unsigned)2, ptr
.length());
1234 TEST(BufferListIterator
, copy
) {
1236 const char *expected
= "ABC";
1237 bl
.append(expected
, 3);
1239 // void copy(unsigned len, char *dest);
1242 char* copy
= (char*)malloc(3);
1243 ::memset(copy
, 'X', 3);
1244 bufferlist::iterator
i(&bl
);
1246 // demonstrates that it seeks back to offset if p == ls->end()
1248 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1250 EXPECT_EQ(0, ::memcmp(copy
, expected
, 2));
1251 EXPECT_EQ('X', copy
[2]);
1254 EXPECT_EQ(0, ::memcmp(copy
, expected
, 3));
1257 // void buffer::list::iterator::copy_deep(unsigned len, ptr &dest)
1261 bufferlist::iterator
i(&bl
);
1262 i
.copy_deep(2, ptr
);
1263 EXPECT_EQ((unsigned)2, ptr
.length());
1264 EXPECT_EQ('A', ptr
[0]);
1265 EXPECT_EQ('B', ptr
[1]);
1268 // void buffer::list::iterator::copy_shallow(unsigned len, ptr &dest)
1272 bufferlist::iterator
i(&bl
);
1273 i
.copy_shallow(2, ptr
);
1274 EXPECT_EQ((unsigned)2, ptr
.length());
1275 EXPECT_EQ('A', ptr
[0]);
1276 EXPECT_EQ('B', ptr
[1]);
1279 // void buffer::list::iterator::copy(unsigned len, list &dest)
1283 bufferlist::iterator
i(&bl
);
1285 // demonstrates that it seeks back to offset if p == ls->end()
1287 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1289 EXPECT_EQ(0, ::memcmp(copy
.c_str(), expected
, 2));
1292 EXPECT_EQ('A', copy
[0]);
1293 EXPECT_EQ('B', copy
[1]);
1294 EXPECT_EQ('A', copy
[2]);
1295 EXPECT_EQ('B', copy
[3]);
1296 EXPECT_EQ('C', copy
[4]);
1297 EXPECT_EQ((unsigned)(2 + 3), copy
.length());
1300 // void buffer::list::iterator::copy_all(list &dest)
1304 bufferlist::iterator
i(&bl
);
1306 // demonstrates that it seeks back to offset if p == ls->end()
1308 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1310 EXPECT_EQ('A', copy
[0]);
1311 EXPECT_EQ('B', copy
[1]);
1312 EXPECT_EQ('C', copy
[2]);
1313 EXPECT_EQ((unsigned)3, copy
.length());
1316 // void copy(unsigned len, std::string &dest)
1320 bufferlist::iterator
i(&bl
);
1322 // demonstrates that it seeks back to offset if p == ls->end()
1324 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1326 EXPECT_EQ(0, ::memcmp(copy
.c_str(), expected
, 2));
1329 EXPECT_EQ('A', copy
[0]);
1330 EXPECT_EQ('B', copy
[1]);
1331 EXPECT_EQ('A', copy
[2]);
1332 EXPECT_EQ('B', copy
[3]);
1333 EXPECT_EQ('C', copy
[4]);
1334 EXPECT_EQ((unsigned)(2 + 3), copy
.length());
1338 TEST(BufferListIterator
, copy_in
) {
1340 const char *existing
= "XXX";
1341 bl
.append(existing
, 3);
1343 // void buffer::list::iterator::copy_in(unsigned len, const char *src)
1346 bufferlist::iterator
i(&bl
);
1348 // demonstrates that it seeks back to offset if p == ls->end()
1350 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1351 const char *expected
= "ABC";
1352 i
.copy_in(3, expected
);
1353 EXPECT_EQ(0, ::memcmp(bl
.c_str(), expected
, 3));
1354 EXPECT_EQ('A', bl
[0]);
1355 EXPECT_EQ('B', bl
[1]);
1356 EXPECT_EQ('C', bl
[2]);
1357 EXPECT_EQ((unsigned)3, bl
.length());
1360 // void buffer::list::iterator::copy_in(unsigned len, const list& otherl)
1363 bufferlist::iterator
i(&bl
);
1365 // demonstrates that it seeks back to offset if p == ls->end()
1367 EXPECT_THROW(i
.advance(200), buffer::end_of_buffer
);
1368 bufferlist expected
;
1369 expected
.append("ABC", 3);
1370 i
.copy_in(3, expected
);
1371 EXPECT_EQ(0, ::memcmp(bl
.c_str(), expected
.c_str(), 3));
1372 EXPECT_EQ('A', bl
[0]);
1373 EXPECT_EQ('B', bl
[1]);
1374 EXPECT_EQ('C', bl
[2]);
1375 EXPECT_EQ((unsigned)3, bl
.length());
1379 // iterator& buffer::list::const_iterator::operator++()
1380 TEST(BufferListConstIterator
, operator_plus_plus
) {
1383 bufferlist::const_iterator
i(&bl
);
1384 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1386 bl
.append("ABC", 3);
1388 const bufferlist
const_bl(bl
);
1389 bufferlist::const_iterator
i(const_bl
.begin());
1396 TEST(BufferList
, constructors
) {
1402 ASSERT_EQ((unsigned)0, bl
.length());
1405 // list(unsigned prealloc)
1409 ASSERT_EQ((unsigned)0, bl
.length());
1411 ASSERT_EQ('A', bl
[0]);
1414 // list(const list& other)
1419 ASSERT_EQ('A', bl
[0]);
1420 bufferlist
copy(bl
);
1421 ASSERT_EQ('A', copy
[0]);
1424 // list(list&& other)
1429 bufferlist copy
= std::move(bl
);
1430 ASSERT_EQ(0U, bl
.length());
1431 ASSERT_EQ(1U, copy
.length());
1432 ASSERT_EQ('A', copy
[0]);
1436 void bench_bufferlist_alloc(int size
, int num
, int per
)
1438 utime_t start
= ceph_clock_now();
1439 for (int i
=0; i
<num
; ++i
) {
1441 for (int j
=0; j
<per
; ++j
)
1442 bl
.append(buffer::create(size
));
1444 utime_t end
= ceph_clock_now();
1445 cout
<< num
<< " alloc of size " << size
1446 << " in " << (end
- start
) << std::endl
;
1449 TEST(BufferList
, BenchAlloc
) {
1450 bench_bufferlist_alloc(32768, 100000, 16);
1451 bench_bufferlist_alloc(25000, 100000, 16);
1452 bench_bufferlist_alloc(16384, 100000, 16);
1453 bench_bufferlist_alloc(10000, 100000, 16);
1454 bench_bufferlist_alloc(8192, 100000, 16);
1455 bench_bufferlist_alloc(6000, 100000, 16);
1456 bench_bufferlist_alloc(4096, 100000, 16);
1457 bench_bufferlist_alloc(1024, 100000, 16);
1458 bench_bufferlist_alloc(256, 100000, 16);
1459 bench_bufferlist_alloc(32, 100000, 16);
1460 bench_bufferlist_alloc(4, 100000, 16);
1463 TEST(BufferList
, operator_equal
) {
1465 // list& operator= (const list& other)
1468 bl
.append("ABC", 3);
1471 bl
.copy(1, 1, dest
);
1472 ASSERT_EQ('B', dest
[0]);
1475 bufferlist copy
= bl
;
1477 copy
.copy(1, 1, dest
);
1478 ASSERT_EQ('B', dest
[0]);
1482 // list& operator= (list&& other)
1484 bufferlist move
= std::move(bl
);
1487 move
.copy(1, 1, dest
);
1488 ASSERT_EQ('B', dest
[0]);
1490 EXPECT_TRUE(move
.length());
1491 EXPECT_TRUE(!bl
.length());
1494 TEST(BufferList
, buffers
) {
1496 ASSERT_EQ((unsigned)0, bl
.get_num_buffers());
1498 ASSERT_EQ((unsigned)1, bl
.get_num_buffers());
1501 TEST(BufferList
, to_str
) {
1505 ASSERT_EQ(bl
.to_str(), string("foo"));
1508 bufferptr
a("foobarbaz", 9);
1509 bufferptr
b("123456789", 9);
1510 bufferptr
c("ABCDEFGHI", 9);
1515 ASSERT_EQ(bl
.to_str(), string("foobarbaz123456789ABCDEFGHI"));
1519 TEST(BufferList
, get_contiguous
) {
1521 bufferptr
a("foobarbaz", 9);
1522 bufferptr
b("123456789", 9);
1523 bufferptr
c("ABCDEFGHI", 9);
1525 ASSERT_EQ(0, bl
.get_contiguous(0, 0));
1530 ASSERT_EQ(3u, bl
.get_num_buffers());
1531 ASSERT_EQ(0, memcmp("bar", bl
.get_contiguous(3, 3), 3));
1532 ASSERT_EQ(0, memcmp("456", bl
.get_contiguous(12, 3), 3));
1533 ASSERT_EQ(0, memcmp("ABC", bl
.get_contiguous(18, 3), 3));
1534 ASSERT_EQ(3u, bl
.get_num_buffers());
1535 ASSERT_EQ(0, memcmp("789ABC", bl
.get_contiguous(15, 6), 6));
1536 ASSERT_EQ(2u, bl
.get_num_buffers());
1540 bufferptr
a("foobarbaz", 9);
1541 bufferptr
b("123456789", 9);
1542 bufferptr
c("ABCDEFGHI", 9);
1549 ASSERT_EQ(0, memcmp("789ABCDEFGHI", bl
.get_contiguous(15, 12), 12));
1550 ASSERT_EQ(2u, bl
.get_num_buffers());
1554 bufferptr
a("foobarbaz", 9);
1555 bufferptr
b("123456789", 9);
1556 bufferptr
c("ABCDEFGHI", 9);
1563 ASSERT_EQ(0, memcmp("z123456789AB", bl
.get_contiguous(8, 12), 12));
1564 ASSERT_EQ(1u, bl
.get_num_buffers());
1568 TEST(BufferList
, swap
) {
1579 ASSERT_EQ('B', s1
[0]);
1583 ASSERT_EQ('A', s2
[0]);
1586 TEST(BufferList
, length
) {
1588 ASSERT_EQ((unsigned)0, bl
.length());
1590 ASSERT_EQ((unsigned)1, bl
.length());
1593 TEST(BufferList
, contents_equal
) {
1602 ASSERT_FALSE(bl1
.contents_equal(bl2
)); // different length
1605 ASSERT_TRUE(bl1
.contents_equal(bl2
)); // same length same content
1611 ASSERT_FALSE(bl1
.contents_equal(bl3
)); // same length different content
1614 TEST(BufferList
, is_aligned
) {
1615 const int SIMD_ALIGN
= 32;
1618 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1622 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1626 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1627 bl
.rebuild_aligned(SIMD_ALIGN
);
1628 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1632 bufferptr
ptr(buffer::create_aligned(SIMD_ALIGN
+ 1, SIMD_ALIGN
));
1634 ptr
.set_length(SIMD_ALIGN
);
1636 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1637 bl
.rebuild_aligned(SIMD_ALIGN
);
1638 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1642 TEST(BufferList
, is_n_align_sized
) {
1643 const int SIMD_ALIGN
= 32;
1646 EXPECT_TRUE(bl
.is_n_align_sized(SIMD_ALIGN
));
1651 EXPECT_FALSE(bl
.is_n_align_sized(SIMD_ALIGN
));
1655 bl
.append_zero(SIMD_ALIGN
);
1656 EXPECT_TRUE(bl
.is_n_align_sized(SIMD_ALIGN
));
1660 TEST(BufferList
, is_page_aligned
) {
1663 EXPECT_TRUE(bl
.is_page_aligned());
1667 bufferptr
ptr(buffer::create_page_aligned(2));
1671 EXPECT_FALSE(bl
.is_page_aligned());
1672 bl
.rebuild_page_aligned();
1673 EXPECT_TRUE(bl
.is_page_aligned());
1677 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1679 ptr
.set_length(CEPH_PAGE_SIZE
);
1681 EXPECT_FALSE(bl
.is_page_aligned());
1682 bl
.rebuild_page_aligned();
1683 EXPECT_TRUE(bl
.is_page_aligned());
1687 TEST(BufferList
, is_n_page_sized
) {
1690 EXPECT_TRUE(bl
.is_n_page_sized());
1695 EXPECT_FALSE(bl
.is_n_page_sized());
1699 bl
.append_zero(CEPH_PAGE_SIZE
);
1700 EXPECT_TRUE(bl
.is_n_page_sized());
1704 TEST(BufferList
, rebuild_aligned_size_and_memory
) {
1705 const unsigned SIMD_ALIGN
= 32;
1706 const unsigned BUFFER_SIZE
= 67;
1709 // These two must be concatenated into one memory + size aligned
1712 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1718 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
- 1, SIMD_ALIGN
));
1721 // This one must be left alone
1723 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
, SIMD_ALIGN
));
1726 // These two must be concatenated into one memory + size aligned
1729 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1735 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
- 1, SIMD_ALIGN
));
1738 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1739 EXPECT_FALSE(bl
.is_n_align_sized(BUFFER_SIZE
));
1740 EXPECT_EQ(BUFFER_SIZE
* 3, bl
.length());
1741 EXPECT_FALSE(bl
.front().is_aligned(SIMD_ALIGN
));
1742 EXPECT_FALSE(bl
.front().is_n_align_sized(BUFFER_SIZE
));
1743 EXPECT_EQ(5U, bl
.get_num_buffers());
1744 bl
.rebuild_aligned_size_and_memory(BUFFER_SIZE
, SIMD_ALIGN
);
1745 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1746 EXPECT_TRUE(bl
.is_n_align_sized(BUFFER_SIZE
));
1747 EXPECT_EQ(3U, bl
.get_num_buffers());
1750 TEST(BufferList
, is_zero
) {
1753 EXPECT_TRUE(bl
.is_zero());
1758 EXPECT_FALSE(bl
.is_zero());
1763 EXPECT_TRUE(bl
.is_zero());
1767 TEST(BufferList
, clear
) {
1770 bl
.append_zero(len
);
1772 EXPECT_EQ((unsigned)0, bl
.length());
1773 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1776 TEST(BufferList
, push_front
) {
1778 // void push_front(ptr& bp)
1784 EXPECT_EQ((unsigned)0, bl
.length());
1785 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1792 ptr
.c_str()[0] = 'B';
1794 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1795 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1796 EXPECT_EQ('B', bl
.front()[0]);
1797 EXPECT_EQ(ptr
.get_raw(), bl
.front().get_raw());
1800 // void push_front(raw *r)
1806 ptr
.c_str()[0] = 'B';
1807 bl
.push_front(ptr
.get_raw());
1808 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1809 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1810 EXPECT_EQ('B', bl
.front()[0]);
1811 EXPECT_EQ(ptr
.get_raw(), bl
.front().get_raw());
1814 // void push_front(ptr&& bp)
1819 bl
.push_front(std::move(ptr
));
1820 EXPECT_EQ((unsigned)0, bl
.length());
1821 EXPECT_EQ((unsigned)0, bl
.buffers().size());
1827 ptr
.c_str()[0] = 'B';
1828 bl
.push_front(std::move(ptr
));
1829 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1830 EXPECT_EQ((unsigned)2, bl
.buffers().size());
1831 EXPECT_EQ('B', bl
.buffers().front()[0]);
1832 EXPECT_FALSE(ptr
.get_raw());
1836 TEST(BufferList
, push_back
) {
1838 // void push_back(ptr& bp)
1844 EXPECT_EQ((unsigned)0, bl
.length());
1845 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1852 ptr
.c_str()[0] = 'B';
1854 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1855 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1856 EXPECT_EQ('B', bl
.back()[0]);
1857 EXPECT_EQ(ptr
.get_raw(), bl
.back().get_raw());
1860 // void push_back(raw *r)
1866 ptr
.c_str()[0] = 'B';
1867 bl
.push_back(ptr
.get_raw());
1868 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1869 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1870 EXPECT_EQ('B', bl
.back()[0]);
1871 EXPECT_EQ(ptr
.get_raw(), bl
.back().get_raw());
1874 // void push_back(ptr&& bp)
1879 bl
.push_back(std::move(ptr
));
1880 EXPECT_EQ((unsigned)0, bl
.length());
1881 EXPECT_EQ((unsigned)0, bl
.buffers().size());
1887 ptr
.c_str()[0] = 'B';
1888 bl
.push_back(std::move(ptr
));
1889 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1890 EXPECT_EQ((unsigned)2, bl
.buffers().size());
1891 EXPECT_EQ('B', bl
.buffers().back()[0]);
1892 EXPECT_FALSE(ptr
.get_raw());
1896 TEST(BufferList
, is_contiguous
) {
1898 EXPECT_TRUE(bl
.is_contiguous());
1899 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1901 EXPECT_TRUE(bl
.is_contiguous());
1902 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1905 EXPECT_FALSE(bl
.is_contiguous());
1906 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1909 TEST(BufferList
, rebuild
) {
1912 bufferptr
ptr(buffer::create_page_aligned(2));
1918 EXPECT_FALSE(bl
.is_page_aligned());
1920 EXPECT_EQ(1U, bl
.length());
1921 EXPECT_EQ('Y', *bl
.begin());
1925 const std::string
str(CEPH_PAGE_SIZE
, 'X');
1926 bl
.append(str
.c_str(), str
.size());
1927 bl
.append(str
.c_str(), str
.size());
1928 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1929 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1931 EXPECT_TRUE(bl
.is_page_aligned());
1932 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1941 EXPECT_EQ((unsigned)1, bl
.length());
1942 bufferlist::iterator p
= bl
.begin();
1945 EXPECT_EQ(0, memcmp(dst
, "X", 1));
1949 TEST(BufferList
, rebuild_page_aligned
) {
1953 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1955 ptr
.set_length(CEPH_PAGE_SIZE
);
1958 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1959 EXPECT_FALSE(bl
.is_page_aligned());
1960 bl
.rebuild_page_aligned();
1961 EXPECT_TRUE(bl
.is_page_aligned());
1962 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1966 bufferptr
ptr(buffer::create_page_aligned(1));
1967 char *p
= ptr
.c_str();
1969 bl
.rebuild_page_aligned();
1970 EXPECT_EQ(p
, bl
.front().c_str());
1975 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
));
1976 EXPECT_TRUE(ptr
.is_page_aligned());
1977 EXPECT_TRUE(ptr
.is_n_page_sized());
1981 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1982 EXPECT_TRUE(ptr
.is_page_aligned());
1983 EXPECT_FALSE(ptr
.is_n_page_sized());
1987 bufferptr
ptr(buffer::create_page_aligned(2));
1990 EXPECT_FALSE(ptr
.is_page_aligned());
1991 EXPECT_FALSE(ptr
.is_n_page_sized());
1995 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
- 2));
1996 EXPECT_TRUE(ptr
.is_page_aligned());
1997 EXPECT_FALSE(ptr
.is_n_page_sized());
2001 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
));
2002 EXPECT_TRUE(ptr
.is_page_aligned());
2003 EXPECT_TRUE(ptr
.is_n_page_sized());
2007 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
2009 ptr
.set_length(CEPH_PAGE_SIZE
);
2010 EXPECT_FALSE(ptr
.is_page_aligned());
2011 EXPECT_TRUE(ptr
.is_n_page_sized());
2014 EXPECT_EQ((unsigned)6, bl
.get_num_buffers());
2015 EXPECT_TRUE((bl
.length() & ~CEPH_PAGE_MASK
) == 0);
2016 EXPECT_FALSE(bl
.is_page_aligned());
2017 bl
.rebuild_page_aligned();
2018 EXPECT_TRUE(bl
.is_page_aligned());
2019 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2023 TEST(BufferList
, claim
) {
2034 EXPECT_EQ((unsigned)4, to
.length());
2035 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
2037 EXPECT_EQ((unsigned)2, to
.length());
2038 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
2039 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
2040 EXPECT_EQ((unsigned)0, from
.length());
2043 TEST(BufferList
, claim_append
) {
2054 EXPECT_EQ((unsigned)4, to
.length());
2055 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
2056 to
.claim_append(from
);
2057 EXPECT_EQ((unsigned)(4 + 2), to
.length());
2058 EXPECT_EQ((unsigned)4, to
.front().length());
2059 EXPECT_EQ((unsigned)2, to
.back().length());
2060 EXPECT_EQ((unsigned)2, to
.get_num_buffers());
2061 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
2062 EXPECT_EQ((unsigned)0, from
.length());
2065 TEST(BufferList
, claim_prepend
) {
2076 EXPECT_EQ((unsigned)4, to
.length());
2077 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
2078 to
.claim_prepend(from
);
2079 EXPECT_EQ((unsigned)(2 + 4), to
.length());
2080 EXPECT_EQ((unsigned)2, to
.front().length());
2081 EXPECT_EQ((unsigned)4, to
.back().length());
2082 EXPECT_EQ((unsigned)2, to
.get_num_buffers());
2083 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
2084 EXPECT_EQ((unsigned)0, from
.length());
2087 TEST(BufferList
, begin
) {
2090 bufferlist::iterator i
= bl
.begin();
2094 TEST(BufferList
, end
) {
2097 bufferlist::iterator i
= bl
.end();
2102 TEST(BufferList
, copy
) {
2104 // void copy(unsigned off, unsigned len, char *dest) const;
2108 EXPECT_THROW(bl
.copy((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer
);
2109 const char *expected
= "ABC";
2110 bl
.append(expected
);
2111 char *dest
= new char[2];
2112 bl
.copy(1, 2, dest
);
2113 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
, 2));
2117 // void copy(unsigned off, unsigned len, list &dest) const;
2122 EXPECT_THROW(bl
.copy((unsigned)100, (unsigned)100, dest
), buffer::end_of_buffer
);
2123 const char *expected
= "ABC";
2124 bl
.append(expected
);
2125 bl
.copy(1, 2, dest
);
2126 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
.c_str(), 2));
2129 // void copy(unsigned off, unsigned len, std::string &dest) const;
2134 EXPECT_THROW(bl
.copy((unsigned)100, (unsigned)100, dest
), buffer::end_of_buffer
);
2135 const char *expected
= "ABC";
2136 bl
.append(expected
);
2137 bl
.copy(1, 2, dest
);
2138 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
.c_str(), 2));
2142 TEST(BufferList
, copy_in
) {
2144 // void copy_in(unsigned off, unsigned len, const char *src);
2149 EXPECT_THROW(bl
.copy_in((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer
);
2150 bl
.copy_in(1, 2, "AB");
2151 EXPECT_EQ(0, ::memcmp("XAB", bl
.c_str(), 3));
2154 // void copy_in(unsigned off, unsigned len, const list& src);
2161 EXPECT_THROW(bl
.copy_in((unsigned)100, (unsigned)100, src
), buffer::end_of_buffer
);
2162 bl
.copy_in(1, 2, src
);
2163 EXPECT_EQ(0, ::memcmp("XAB", bl
.c_str(), 3));
2167 TEST(BufferList
, append
) {
2169 // void append(char c);
2173 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2175 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2176 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
2179 // void append(const char *data, unsigned len);
2182 bufferlist
bl(CEPH_PAGE_SIZE
);
2183 std::string
str(CEPH_PAGE_SIZE
* 2, 'X');
2184 bl
.append(str
.c_str(), str
.size());
2185 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2186 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.front().length());
2187 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.back().length());
2190 // void append(const std::string& s);
2193 bufferlist
bl(CEPH_PAGE_SIZE
);
2194 std::string
str(CEPH_PAGE_SIZE
* 2, 'X');
2196 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2197 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.front().length());
2198 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.back().length());
2201 // void append(const ptr& bp);
2205 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2206 EXPECT_EQ((unsigned)0, bl
.length());
2210 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2211 EXPECT_EQ((unsigned)0, bl
.length());
2216 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2217 EXPECT_EQ((unsigned)3, bl
.length());
2221 // void append(const ptr& bp, unsigned off, unsigned len);
2226 bufferptr
back(bl
.back());
2228 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2229 EXPECT_EQ((unsigned)1, bl
.length());
2231 PrCtl unset_dumpable
;
2232 EXPECT_DEATH(bl
.append(in
, (unsigned)100, (unsigned)100), "");
2234 EXPECT_LT((unsigned)0, in
.unused_tail_length());
2236 bl
.append(in
, back
.end(), 1);
2237 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2238 EXPECT_EQ((unsigned)2, bl
.length());
2239 EXPECT_EQ('B', bl
[1]);
2243 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2244 EXPECT_EQ((unsigned)0, bl
.length());
2247 ptr
.append("AB", 2);
2248 bl
.append(ptr
, 1, 1);
2249 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2250 EXPECT_EQ((unsigned)1, bl
.length());
2253 // void append(const list& bl);
2261 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2262 EXPECT_EQ('B', bl
[1]);
2265 // void append(std::istream& in);
2269 std::string
expected("ABC\nDEF\n");
2270 std::istringstream
is("ABC\n\nDEF");
2272 EXPECT_EQ(0, ::memcmp(expected
.c_str(), bl
.c_str(), expected
.size()));
2273 EXPECT_EQ(expected
.size(), bl
.length());
2276 // void append(ptr&& bp);
2280 EXPECT_EQ((unsigned)0, bl
.buffers().size());
2281 EXPECT_EQ((unsigned)0, bl
.length());
2284 bl
.append(std::move(ptr
));
2285 EXPECT_EQ((unsigned)0, bl
.buffers().size());
2286 EXPECT_EQ((unsigned)0, bl
.length());
2290 bl
.append(std::move(ptr
));
2291 EXPECT_EQ((unsigned)1, bl
.buffers().size());
2292 EXPECT_EQ((unsigned)3, bl
.length());
2293 EXPECT_FALSE(ptr
.get_raw());
2298 TEST(BufferList
, append_zero
) {
2301 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2302 EXPECT_EQ((unsigned)1, bl
.length());
2304 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2305 EXPECT_EQ((unsigned)2, bl
.length());
2306 EXPECT_EQ('\0', bl
[1]);
2309 TEST(BufferList
, operator_brackets
) {
2311 EXPECT_THROW(bl
[1], buffer::end_of_buffer
);
2316 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2317 EXPECT_EQ('B', bl
[1]);
2320 TEST(BufferList
, c_str
) {
2322 EXPECT_EQ((const char*)NULL
, bl
.c_str());
2327 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2328 EXPECT_EQ(0, ::memcmp("AB", bl
.c_str(), 2));
2331 TEST(BufferList
, substr_of
) {
2333 EXPECT_THROW(bl
.substr_of(bl
, 1, 1), buffer::end_of_buffer
);
2340 for (unsigned i
= 0; i
< 4; i
++) {
2341 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2344 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2347 other
.append("TO BE CLEARED");
2348 other
.substr_of(bl
, 4, 4);
2349 EXPECT_EQ((unsigned)2, other
.get_num_buffers());
2350 EXPECT_EQ((unsigned)4, other
.length());
2351 EXPECT_EQ(0, ::memcmp("EFGH", other
.c_str(), 4));
2354 TEST(BufferList
, splice
) {
2356 EXPECT_THROW(bl
.splice(1, 1), buffer::end_of_buffer
);
2363 for (unsigned i
= 0; i
< 4; i
++) {
2364 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2367 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2372 bl
.splice(4, 4, &other
);
2373 EXPECT_EQ((unsigned)3, other
.get_num_buffers());
2374 EXPECT_EQ((unsigned)5, other
.length());
2375 EXPECT_EQ(0, ::memcmp("XEFGH", other
.c_str(), other
.length()));
2376 EXPECT_EQ((unsigned)8, bl
.length());
2379 EXPECT_EQ(0, ::memcmp("ABCDIJKL", tmp
.c_str(), tmp
.length()));
2383 EXPECT_EQ((unsigned)4, bl
.length());
2384 EXPECT_EQ(0, ::memcmp("ABCD", bl
.c_str(), bl
.length()));
2388 bufferptr
ptr1("0123456789", 10);
2390 bufferptr
ptr2("abcdefghij", 10);
2391 bl
.append(ptr2
, 5, 5);
2393 bl
.splice(10, 4, &other
);
2394 EXPECT_EQ((unsigned)11, bl
.length());
2395 EXPECT_EQ(0, ::memcmp("fghi", other
.c_str(), other
.length()));
2399 TEST(BufferList
, write
) {
2400 std::ostringstream stream
;
2403 bl
.write(1, 2, stream
);
2404 EXPECT_EQ("BC", stream
.str());
2407 TEST(BufferList
, encode_base64
) {
2411 bl
.encode_base64(other
);
2412 const char *expected
= "QUJDRA==";
2413 EXPECT_EQ(0, ::memcmp(expected
, other
.c_str(), strlen(expected
)));
2416 TEST(BufferList
, decode_base64
) {
2418 bl
.append("QUJDRA==");
2420 other
.decode_base64(bl
);
2421 const char *expected
= "ABCD";
2422 EXPECT_EQ(0, ::memcmp(expected
, other
.c_str(), strlen(expected
)));
2423 bufferlist malformed
;
2424 malformed
.append("QUJDRA");
2425 EXPECT_THROW(other
.decode_base64(malformed
), buffer::malformed_input
);
2428 TEST(BufferList
, hexdump
) {
2430 std::ostringstream stream
;
2431 bl
.append("013245678901234\0006789012345678901234", 32);
2433 EXPECT_EQ("00000000 30 31 33 32 34 35 36 37 38 39 30 31 32 33 34 00 |013245678901234.|\n"
2434 "00000010 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 |6789012345678901|\n"
2439 TEST(BufferList
, read_file
) {
2443 EXPECT_EQ(-ENOENT
, bl
.read_file("UNLIKELY", &error
));
2444 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s ; chmod 0 %s", FILENAME
, FILENAME
);
2445 EXPECT_EQ(0, ::system(cmd
));
2446 if (getuid() != 0) {
2447 EXPECT_EQ(-EACCES
, bl
.read_file(FILENAME
, &error
));
2449 snprintf(cmd
, sizeof(cmd
), "chmod +r %s", FILENAME
);
2450 EXPECT_EQ(0, ::system(cmd
));
2451 EXPECT_EQ(0, bl
.read_file(FILENAME
, &error
));
2453 EXPECT_EQ((unsigned)4, bl
.length());
2454 std::string
actual(bl
.c_str(), bl
.length());
2455 EXPECT_EQ("ABC\n", actual
);
2458 TEST(BufferList
, read_fd
) {
2461 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s", FILENAME
);
2462 EXPECT_EQ(0, ::system(cmd
));
2465 EXPECT_EQ(-EBADF
, bl
.read_fd(fd
, len
));
2466 fd
= ::open(FILENAME
, O_RDONLY
);
2467 EXPECT_EQ(len
, (unsigned)bl
.read_fd(fd
, len
));
2468 //EXPECT_EQ(CEPH_BUFFER_APPEND_SIZE - len, bl.front().unused_tail_length());
2469 EXPECT_EQ(len
, bl
.length());
2474 TEST(BufferList
, write_file
) {
2478 EXPECT_EQ(-ENOENT
, bl
.write_file("un/like/ly", mode
));
2480 EXPECT_EQ(0, bl
.write_file(FILENAME
, mode
));
2482 memset(&st
, 0, sizeof(st
));
2483 ::stat(FILENAME
, &st
);
2484 EXPECT_EQ((unsigned)(mode
| S_IFREG
), st
.st_mode
);
2488 TEST(BufferList
, write_fd
) {
2490 int fd
= ::open(FILENAME
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2492 for (unsigned i
= 0; i
< IOV_MAX
* 2; i
++) {
2493 bufferptr
ptr("A", 1);
2496 EXPECT_EQ(0, bl
.write_fd(fd
));
2499 memset(&st
, 0, sizeof(st
));
2500 ::stat(FILENAME
, &st
);
2501 EXPECT_EQ(IOV_MAX
* 2, st
.st_size
);
2505 TEST(BufferList
, write_fd_offset
) {
2507 int fd
= ::open(FILENAME
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2509 for (unsigned i
= 0; i
< IOV_MAX
* 2; i
++) {
2510 bufferptr
ptr("A", 1);
2513 uint64_t offset
= 200;
2514 EXPECT_EQ(0, bl
.write_fd(fd
, offset
));
2517 memset(&st
, 0, sizeof(st
));
2518 ::stat(FILENAME
, &st
);
2519 EXPECT_EQ(IOV_MAX
* 2 + offset
, (unsigned)st
.st_size
);
2523 TEST(BufferList
, crc32c
) {
2527 crc
= bl
.crc32c(crc
);
2528 EXPECT_EQ((unsigned)0xB3109EBF, crc
);
2529 crc
= bl
.crc32c(crc
);
2530 EXPECT_EQ((unsigned)0x5FA5C0CC, crc
);
2533 TEST(BufferList
, crc32c_append
) {
2537 for (int j
= 0; j
< 200; ++j
) {
2539 for (int i
= 0; i
< 200; ++i
) {
2544 bl
.crc32c(rand()); // mess with the cached bufferptr crc values
2547 ASSERT_EQ(bl1
.crc32c(0), bl2
.crc32c(0));
2550 TEST(BufferList
, crc32c_append_perf
) {
2551 int len
= 256 * 1024 * 1024;
2556 std::cout
<< "populating large buffers (a, b=c=d)" << std::endl
;
2557 char *pa
= a
.c_str();
2558 char *pb
= b
.c_str();
2559 char *pc
= c
.c_str();
2560 char *pd
= c
.c_str();
2561 for (int i
=0; i
<len
; i
++) {
2562 pa
[i
] = (i
& 0xff) ^ 73;
2563 pb
[i
] = (i
& 0xff) ^ 123;
2564 pc
[i
] = (i
& 0xff) ^ 123;
2565 pd
[i
] = (i
& 0xff) ^ 123;
2568 // track usage of cached crcs
2569 buffer::track_cached_crc(true);
2571 int base_cached
= buffer::get_cached_crc();
2572 int base_cached_adjusted
= buffer::get_cached_crc_adjusted();
2579 utime_t start
= ceph_clock_now();
2580 uint32_t r
= bla
.crc32c(0);
2581 utime_t end
= ceph_clock_now();
2582 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2583 std::cout
<< "a.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2584 ASSERT_EQ(r
, 1138817026u);
2586 assert(buffer::get_cached_crc() == 0 + base_cached
);
2588 utime_t start
= ceph_clock_now();
2589 uint32_t r
= bla
.crc32c(0);
2590 utime_t end
= ceph_clock_now();
2591 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2592 std::cout
<< "a.crc32c(0) (again) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2593 ASSERT_EQ(r
, 1138817026u);
2595 assert(buffer::get_cached_crc() == 1 + base_cached
);
2598 utime_t start
= ceph_clock_now();
2599 uint32_t r
= bla
.crc32c(5);
2600 utime_t end
= ceph_clock_now();
2601 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2602 std::cout
<< "a.crc32c(5) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2603 ASSERT_EQ(r
, 3239494520u);
2605 assert(buffer::get_cached_crc() == 1 + base_cached
);
2606 assert(buffer::get_cached_crc_adjusted() == 1 + base_cached_adjusted
);
2608 utime_t start
= ceph_clock_now();
2609 uint32_t r
= bla
.crc32c(5);
2610 utime_t end
= ceph_clock_now();
2611 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2612 std::cout
<< "a.crc32c(5) (again) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2613 ASSERT_EQ(r
, 3239494520u);
2615 assert(buffer::get_cached_crc() == 1 + base_cached
);
2616 assert(buffer::get_cached_crc_adjusted() == 2 + base_cached_adjusted
);
2619 utime_t start
= ceph_clock_now();
2620 uint32_t r
= blb
.crc32c(0);
2621 utime_t end
= ceph_clock_now();
2622 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2623 std::cout
<< "b.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2624 ASSERT_EQ(r
, 2481791210u);
2626 assert(buffer::get_cached_crc() == 1 + base_cached
);
2628 utime_t start
= ceph_clock_now();
2629 uint32_t r
= blb
.crc32c(0);
2630 utime_t end
= ceph_clock_now();
2631 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2632 std::cout
<< "b.crc32c(0) (again)= " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2633 ASSERT_EQ(r
, 2481791210u);
2635 assert(buffer::get_cached_crc() == 2 + base_cached
);
2641 utime_t start
= ceph_clock_now();
2642 uint32_t r
= ab
.crc32c(0);
2643 utime_t end
= ceph_clock_now();
2644 float rate
= (float)ab
.length() / (float)(1024*1024) / (float)(end
- start
);
2645 std::cout
<< "ab.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2646 ASSERT_EQ(r
, 2988268779u);
2648 assert(buffer::get_cached_crc() == 3 + base_cached
);
2649 assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted
);
2654 utime_t start
= ceph_clock_now();
2655 uint32_t r
= ac
.crc32c(0);
2656 utime_t end
= ceph_clock_now();
2657 float rate
= (float)ac
.length() / (float)(1024*1024) / (float)(end
- start
);
2658 std::cout
<< "ac.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2659 ASSERT_EQ(r
, 2988268779u);
2661 assert(buffer::get_cached_crc() == 4 + base_cached
);
2662 assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted
);
2668 utime_t start
= ceph_clock_now();
2669 uint32_t r
= ba
.crc32c(0);
2670 utime_t end
= ceph_clock_now();
2671 float rate
= (float)ba
.length() / (float)(1024*1024) / (float)(end
- start
);
2672 std::cout
<< "ba.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2673 ASSERT_EQ(r
, 169240695u);
2675 assert(buffer::get_cached_crc() == 5 + base_cached
);
2676 assert(buffer::get_cached_crc_adjusted() == 4 + base_cached_adjusted
);
2678 utime_t start
= ceph_clock_now();
2679 uint32_t r
= ba
.crc32c(5);
2680 utime_t end
= ceph_clock_now();
2681 float rate
= (float)ba
.length() / (float)(1024*1024) / (float)(end
- start
);
2682 std::cout
<< "ba.crc32c(5) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2683 ASSERT_EQ(r
, 1265464778u);
2685 assert(buffer::get_cached_crc() == 5 + base_cached
);
2686 assert(buffer::get_cached_crc_adjusted() == 6 + base_cached_adjusted
);
2688 cout
<< "crc cache hits (same start) = " << buffer::get_cached_crc() << std::endl
;
2689 cout
<< "crc cache hits (adjusted) = " << buffer::get_cached_crc_adjusted() << std::endl
;
2692 TEST(BufferList
, compare
) {
2700 // bool operator>(bufferlist& l, bufferlist& r)
2702 ASSERT_FALSE(a
> ab
);
2703 ASSERT_TRUE(ab
> a
);
2704 ASSERT_TRUE(ac
> ab
);
2705 ASSERT_FALSE(ab
> ac
);
2706 ASSERT_FALSE(ab
> ab
);
2708 // bool operator>=(bufferlist& l, bufferlist& r)
2710 ASSERT_FALSE(a
>= ab
);
2711 ASSERT_TRUE(ab
>= a
);
2712 ASSERT_TRUE(ac
>= ab
);
2713 ASSERT_FALSE(ab
>= ac
);
2714 ASSERT_TRUE(ab
>= ab
);
2716 // bool operator<(bufferlist& l, bufferlist& r)
2718 ASSERT_TRUE(a
< ab
);
2719 ASSERT_FALSE(ab
< a
);
2720 ASSERT_FALSE(ac
< ab
);
2721 ASSERT_TRUE(ab
< ac
);
2722 ASSERT_FALSE(ab
< ab
);
2724 // bool operator<=(bufferlist& l, bufferlist& r)
2726 ASSERT_TRUE(a
<= ab
);
2727 ASSERT_FALSE(ab
<= a
);
2728 ASSERT_FALSE(ac
<= ab
);
2729 ASSERT_TRUE(ab
<= ac
);
2730 ASSERT_TRUE(ab
<= ab
);
2732 // bool operator==(bufferlist &l, bufferlist &r)
2734 ASSERT_FALSE(a
== ab
);
2735 ASSERT_FALSE(ac
== ab
);
2736 ASSERT_TRUE(ab
== ab
);
2739 TEST(BufferList
, ostream
) {
2740 std::ostringstream stream
;
2746 for (unsigned i
= 0; i
< 2; i
++) {
2747 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2751 std::cerr
<< stream
.str() << std::endl
;
2752 EXPECT_GT(stream
.str().size(), stream
.str().find("list(len=6,"));
2753 EXPECT_GT(stream
.str().size(), stream
.str().find("len 3 nref 1),\n"));
2754 EXPECT_GT(stream
.str().size(), stream
.str().find("len 3 nref 1)\n"));
2757 TEST(BufferList
, zero
) {
2764 EXPECT_EQ('A', bl
[0]);
2766 EXPECT_EQ('\0', bl
[0]);
2769 // void zero(unsigned o, unsigned l)
2779 bufferptr
ptr(s
[0], strlen(s
[0]));
2781 bl
.zero((unsigned)0, (unsigned)1);
2782 EXPECT_EQ(0, ::memcmp("\0BC", bl
.c_str(), 3));
2786 for (unsigned i
= 0; i
< 4; i
++) {
2787 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2791 PrCtl unset_dumpable
;
2792 EXPECT_DEATH(bl
.zero((unsigned)0, (unsigned)2000), "");
2794 bl
.zero((unsigned)2, (unsigned)5);
2795 EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl
.c_str(), 9));
2799 for (unsigned i
= 0; i
< 4; i
++) {
2800 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2803 bl
.zero((unsigned)3, (unsigned)3);
2804 EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl
.c_str(), 9));
2810 memset(ptr1
.c_str(), 'a', 4);
2811 memset(ptr2
.c_str(), 'b', 4);
2814 bl
.zero((unsigned)2, (unsigned)4);
2815 EXPECT_EQ(0, ::memcmp("aa\0\0\0\0bb", bl
.c_str(), 8));
2819 TEST(BufferList
, EmptyAppend
) {
2823 ASSERT_EQ(bl
.begin().end(), 1);
2826 TEST(BufferList
, TestPtrAppend
) {
2828 char correct
[MAX_TEST
];
2830 int length
= random() % 5 > 0 ? random() % 1000 : 0;
2831 while (curpos
+ length
< MAX_TEST
) {
2836 char *current
= correct
+ curpos
;
2837 for (int i
= 0; i
< length
; ++i
) {
2838 char next
= random() % 255;
2839 correct
[curpos
++] = next
;
2841 bufferptr
ptr(current
, length
);
2844 length
= random() % 5 > 0 ? random() % 1000 : 0;
2846 ASSERT_EQ(memcmp(bl
.c_str(), correct
, curpos
), 0);
2849 TEST(BufferList
, TestDirectAppend
) {
2851 char correct
[MAX_TEST
];
2853 int length
= random() % 5 > 0 ? random() % 1000 : 0;
2854 while (curpos
+ length
< MAX_TEST
) {
2855 char *current
= correct
+ curpos
;
2856 for (int i
= 0; i
< length
; ++i
) {
2857 char next
= random() % 255;
2858 correct
[curpos
++] = next
;
2860 bl
.append(current
, length
);
2861 length
= random() % 5 > 0 ? random() % 1000 : 0;
2863 ASSERT_EQ(memcmp(bl
.c_str(), correct
, curpos
), 0);
2866 TEST(BufferList
, TestCloneNonShareable
) {
2868 std::string str
= "sharetest";
2869 bl
.append(str
.c_str(), 9);
2870 bufferlist bl_share
;
2872 bufferlist bl_noshare
;
2873 buffer::ptr unraw
= buffer::create_unshareable(10);
2874 unraw
.copy_in(0, 9, str
.c_str());
2875 bl_noshare
.append(unraw
);
2876 bufferlist bl_copied_share
= bl_share
;
2877 bufferlist bl_copied_noshare
= bl_noshare
;
2879 // assert shared bufferlist has same buffers
2880 bufferlist::iterator iter_bl
= bl
.begin();
2881 bufferlist::iterator iter_bl_share
= bl_share
.begin();
2882 // ok, this considers ptr::off, but it's still a true assertion (and below)
2883 ASSERT_TRUE(iter_bl
.get_current_ptr().c_str() ==
2884 iter_bl_share
.get_current_ptr().c_str());
2886 // assert copy of shareable bufferlist has same buffers
2887 iter_bl
= bl
.begin();
2888 bufferlist::iterator iter_bl_copied_share
= bl_copied_share
.begin();
2889 ASSERT_TRUE(iter_bl
.get_current_ptr().c_str() ==
2890 iter_bl_copied_share
.get_current_ptr().c_str());
2892 // assert copy of non-shareable bufferlist has different buffers
2893 bufferlist::iterator iter_bl_copied_noshare
= bl_copied_noshare
.begin();
2894 ASSERT_FALSE(iter_bl
.get_current_ptr().c_str() ==
2895 iter_bl_copied_noshare
.get_current_ptr().c_str());
2897 // assert that claim with CLAIM_ALLOW_NONSHAREABLE overrides safe-sharing
2898 bufferlist bl_claim_noshare_override
;
2899 void* addr
= bl_noshare
.begin().get_current_ptr().c_str();
2900 bl_claim_noshare_override
.claim(bl_noshare
,
2901 buffer::list::CLAIM_ALLOW_NONSHAREABLE
);
2902 bufferlist::iterator iter_bl_noshare_override
=
2903 bl_claim_noshare_override
.begin();
2904 ASSERT_TRUE(addr
/* the original first segment of bl_noshare() */ ==
2905 iter_bl_noshare_override
.get_current_ptr().c_str());
2908 TEST(BufferList
, TestCopyAll
) {
2909 const static size_t BIG_SZ
= 10737414;
2910 ceph::shared_ptr
<unsigned char> big(
2911 (unsigned char*)malloc(BIG_SZ
), free
);
2912 unsigned char c
= 0;
2913 for (size_t i
= 0; i
< BIG_SZ
; ++i
) {
2917 bl
.append((const char*)big
.get(), BIG_SZ
);
2918 bufferlist::iterator i
= bl
.begin();
2921 ASSERT_EQ(bl2
.length(), BIG_SZ
);
2922 ceph::shared_ptr
<unsigned char> big2(
2923 (unsigned char*)malloc(BIG_SZ
), free
);
2924 bl2
.copy(0, BIG_SZ
, (char*)big2
.get());
2925 ASSERT_EQ(memcmp(big
.get(), big2
.get(), BIG_SZ
), 0);
2928 TEST(BufferList
, InvalidateCrc
) {
2929 const static size_t buffer_size
= 262144;
2930 ceph::shared_ptr
<unsigned char> big(
2931 (unsigned char*)malloc(buffer_size
), free
);
2932 unsigned char c
= 0;
2933 char* ptr
= (char*) big
.get();
2935 for (size_t i
= 0; i
< buffer_size
; ++i
) {
2940 // test for crashes (shouldn't crash)
2941 bl
.invalidate_crc();
2943 // put data into bufferlist
2944 bl
.append((const char*)big
.get(), buffer_size
);
2947 __u32 crc
= bl
.crc32c(0);
2949 // modify data in bl without its knowledge
2950 inptr
= (char*) bl
.c_str();
2952 for (size_t i
= 0; i
< buffer_size
; ++i
) {
2956 // make sure data in bl are now different than in big
2957 EXPECT_NE(memcmp((void*) ptr
, (void*) inptr
, buffer_size
), 0);
2959 // crc should remain the same
2960 __u32 new_crc
= bl
.crc32c(0);
2961 EXPECT_EQ(crc
, new_crc
);
2963 // force crc invalidate, check if it is updated
2964 bl
.invalidate_crc();
2965 EXPECT_NE(crc
, bl
.crc32c(0));
2968 TEST(BufferList
, TestIsProvidedBuffer
) {
2971 bl
.push_back(buffer::create_static(100, buff
));
2972 ASSERT_TRUE(bl
.is_provided_buffer(buff
));
2973 bl
.append_zero(100);
2974 ASSERT_FALSE(bl
.is_provided_buffer(buff
));
2977 TEST(BufferHash
, all
) {
2982 EXPECT_EQ((unsigned)0, hash
.digest());
2984 EXPECT_EQ((unsigned)0xB3109EBF, hash
.digest());
2986 EXPECT_EQ((unsigned)0x5FA5C0CC, hash
.digest());
2992 EXPECT_EQ((unsigned)0, hash
.digest());
2993 bufferhash
& returned_hash
= hash
<< bl
;
2994 EXPECT_EQ(&returned_hash
, &hash
);
2995 EXPECT_EQ((unsigned)0xB3109EBF, hash
.digest());
3001 * compile-command: "cd .. ; make unittest_bufferlist &&
3002 * ulimit -s unlimited ; CEPH_BUFFER_TRACK=true valgrind \
3003 * --max-stackframe=20000000 --tool=memcheck \
3004 * ./unittest_bufferlist # --gtest_filter=BufferList.constructors"