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"
39 #include "include/crc32c.h"
40 #include "common/sctp_crc32.h"
42 #define MAX_TEST 1000000
43 #define FILENAME "bufferlist"
47 TEST(Buffer, constructors) {
48 bool ceph_buffer_track = get_env_bool("CEPH_BUFFER_TRACK");
50 uint64_t history_alloc_bytes = 0;
51 uint64_t history_alloc_num = 0;
55 if (ceph_buffer_track) {
56 EXPECT_EQ(0, buffer::get_total_alloc());
60 bufferptr ptr(buffer::create(len));
61 history_alloc_bytes += len;
63 EXPECT_EQ(len, ptr.length());
64 if (ceph_buffer_track) {
65 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
66 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
67 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
73 if (ceph_buffer_track) {
74 EXPECT_EQ(0, buffer::get_total_alloc());
78 char* str = new char[len];
79 ::memset(str, 'X', len);
80 bufferptr ptr(buffer::claim_char(len, str));
81 if (ceph_buffer_track) {
82 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
83 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
84 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
86 EXPECT_EQ(len, ptr.length());
87 EXPECT_EQ(str, ptr.c_str());
88 bufferptr clone = ptr.clone();
89 history_alloc_bytes += len;
91 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
94 // buffer::create_static
96 if (ceph_buffer_track) {
97 EXPECT_EQ(0, buffer::get_total_alloc());
101 char* str = new char[len];
102 bufferptr ptr(buffer::create_static(len, str));
103 if (ceph_buffer_track) {
104 EXPECT_EQ(0, buffer::get_total_alloc());
105 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
106 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
108 EXPECT_EQ(len, ptr.length());
109 EXPECT_EQ(str, ptr.c_str());
113 // buffer::create_malloc
115 if (ceph_buffer_track) {
116 EXPECT_EQ(0, buffer::get_total_alloc());
120 bufferptr ptr(buffer::create_malloc(len));
121 history_alloc_bytes += len;
123 if (ceph_buffer_track) {
124 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
125 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
126 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
128 EXPECT_EQ(len, ptr.length());
129 // this doesn't throw on my x86_64 wheezy box --sage
130 //EXPECT_THROW(buffer::create_malloc((unsigned)ULLONG_MAX), buffer::bad_alloc);
133 // buffer::claim_malloc
135 if (ceph_buffer_track) {
136 EXPECT_EQ(0, buffer::get_total_alloc());
140 char* str = (char*)malloc(len);
141 ::memset(str, 'X', len);
142 bufferptr ptr(buffer::claim_malloc(len, str));
143 if (ceph_buffer_track) {
144 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
145 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
146 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
148 EXPECT_EQ(len, ptr.length());
149 EXPECT_EQ(str, ptr.c_str());
150 bufferptr clone = ptr.clone();
151 history_alloc_bytes += len;
153 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
158 if (ceph_buffer_track) {
159 EXPECT_EQ(0, buffer::get_total_alloc());
163 const std::string expected(len, 'X');
164 bufferptr ptr(buffer::copy(expected.c_str(), expected.size()));
165 history_alloc_bytes += len;
167 if (ceph_buffer_track) {
168 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
169 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
170 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
172 EXPECT_NE(expected.c_str(), ptr.c_str());
173 EXPECT_EQ(0, ::memcmp(expected.c_str(), ptr.c_str(), len));
176 // buffer::create_page_aligned
178 if (ceph_buffer_track) {
179 EXPECT_EQ(0, buffer::get_total_alloc());
183 bufferptr ptr(buffer::create_page_aligned(len));
184 history_alloc_bytes += len;
186 ::memset(ptr.c_str(), 'X', len);
187 if (ceph_buffer_track) {
188 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
189 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
190 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
192 // doesn't throw on my x86_64 wheezy box --sage
193 //EXPECT_THROW(buffer::create_page_aligned((unsigned)ULLONG_MAX), buffer::bad_alloc);
195 ASSERT_TRUE(ptr.is_page_aligned());
197 bufferptr clone = ptr.clone();
198 history_alloc_bytes += len;
200 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
201 if (ceph_buffer_track) {
202 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
203 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
206 #ifdef CEPH_HAVE_SPLICE
207 if (ceph_buffer_track) {
208 EXPECT_EQ(0, buffer::get_total_alloc());
213 EXPECT_THROW(buffer::create_zero_copy(len, -1, NULL), buffer::error_code);
214 history_alloc_bytes += len;
219 snprintf(cmd, sizeof(cmd), "echo ABC > %s", FILENAME);
220 EXPECT_EQ(0, ::system(cmd));
221 int fd = ::open(FILENAME, O_RDONLY);
222 bufferptr ptr(buffer::create_zero_copy(zc_len, fd, NULL));
223 history_alloc_bytes += zc_len;
225 EXPECT_EQ(zc_len, ptr.length());
226 if (ceph_buffer_track) {
227 EXPECT_EQ(zc_len, (unsigned)buffer::get_total_alloc());
228 EXPECT_EQ(history_alloc_bytes, buffer::get_history_alloc_bytes());
229 EXPECT_EQ(history_alloc_num, buffer::get_history_alloc_num());
235 if (ceph_buffer_track) {
236 EXPECT_EQ(0, buffer::get_total_alloc());
240 void bench_buffer_alloc(int size, int num)
242 utime_t start = ceph_clock_now();
243 for (int i=0; i<num; ++i) {
244 bufferptr p = buffer::create(size);
247 utime_t end = ceph_clock_now();
248 cout << num << " alloc of size " << size
249 << " in " << (end - start) << std::endl;
252 TEST(Buffer, BenchAlloc) {
253 bench_buffer_alloc(16384, 1000000);
254 bench_buffer_alloc(4096, 1000000);
255 bench_buffer_alloc(1024, 1000000);
256 bench_buffer_alloc(256, 1000000);
257 bench_buffer_alloc(32, 1000000);
258 bench_buffer_alloc(4, 1000000);
261 TEST(BufferRaw, ostream) {
263 std::ostringstream stream;
264 stream << *ptr.get_raw();
265 EXPECT_GT(stream.str().size(), stream.str().find("buffer::raw("));
266 EXPECT_GT(stream.str().size(), stream.str().find("len 1 nref 1)"));
269 #ifdef CEPH_HAVE_SPLICE
270 class TestRawPipe : public ::testing::Test {
272 void SetUp() override {
275 snprintf(cmd, sizeof(cmd), "echo ABC > %s", FILENAME);
276 EXPECT_EQ(0, ::system(cmd));
277 fd = ::open(FILENAME, O_RDONLY);
280 void TearDown() override {
288 TEST_F(TestRawPipe, create_zero_copy) {
289 bufferptr ptr(buffer::create_zero_copy(len, fd, NULL));
290 EXPECT_EQ(len, ptr.length());
291 if (get_env_bool("CEPH_BUFFER_TRACK")) {
292 EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
296 TEST_F(TestRawPipe, c_str_no_fd) {
297 EXPECT_THROW(bufferptr ptr(buffer::create_zero_copy(len, -1, NULL)),
301 TEST_F(TestRawPipe, c_str_basic) {
302 bufferptr ptr = bufferptr(buffer::create_zero_copy(len, fd, NULL));
303 EXPECT_EQ(0, memcmp(ptr.c_str(), "ABC\n", len));
304 EXPECT_EQ(len, ptr.length());
307 TEST_F(TestRawPipe, c_str_twice) {
308 // make sure we're creating a copy of the data and not consuming it
309 bufferptr ptr = bufferptr(buffer::create_zero_copy(len, fd, NULL));
310 EXPECT_EQ(len, ptr.length());
311 EXPECT_EQ(0, memcmp(ptr.c_str(), "ABC\n", len));
312 EXPECT_EQ(0, memcmp(ptr.c_str(), "ABC\n", len));
315 TEST_F(TestRawPipe, c_str_basic_offset) {
316 loff_t offset = len - 1;
317 ::lseek(fd, offset, SEEK_SET);
318 bufferptr ptr = bufferptr(buffer::create_zero_copy(len - offset, fd, NULL));
319 EXPECT_EQ(len - offset, ptr.length());
320 EXPECT_EQ(0, memcmp(ptr.c_str(), "\n", len - offset));
323 TEST_F(TestRawPipe, c_str_dest_short) {
324 ::lseek(fd, 1, SEEK_SET);
325 bufferptr ptr = bufferptr(buffer::create_zero_copy(2, fd, NULL));
326 EXPECT_EQ(2u, ptr.length());
327 EXPECT_EQ(0, memcmp(ptr.c_str(), "BC", 2));
330 TEST_F(TestRawPipe, c_str_source_short) {
331 ::lseek(fd, 1, SEEK_SET);
332 bufferptr ptr = bufferptr(buffer::create_zero_copy(len, fd, NULL));
333 EXPECT_EQ(len - 1, ptr.length());
334 EXPECT_EQ(0, memcmp(ptr.c_str(), "BC\n", len - 1));
337 TEST_F(TestRawPipe, c_str_explicit_zero_offset) {
339 ::lseek(fd, 1, SEEK_SET);
340 bufferptr ptr = bufferptr(buffer::create_zero_copy(len, fd, &offset));
341 EXPECT_EQ(len, offset);
342 EXPECT_EQ(len, ptr.length());
343 EXPECT_EQ(0, memcmp(ptr.c_str(), "ABC\n", len));
346 TEST_F(TestRawPipe, c_str_explicit_positive_offset) {
348 bufferptr ptr = bufferptr(buffer::create_zero_copy(len - offset, fd,
350 EXPECT_EQ(len, offset);
351 EXPECT_EQ(len - 1, ptr.length());
352 EXPECT_EQ(0, memcmp(ptr.c_str(), "BC\n", len - 1));
355 TEST_F(TestRawPipe, c_str_explicit_positive_empty_result) {
356 int64_t offset = len;
357 bufferptr ptr = bufferptr(buffer::create_zero_copy(len - offset, fd,
359 EXPECT_EQ(len, offset);
360 EXPECT_EQ(0u, ptr.length());
363 TEST_F(TestRawPipe, c_str_source_short_explicit_offset) {
365 bufferptr ptr = bufferptr(buffer::create_zero_copy(len, fd, &offset));
366 EXPECT_EQ(len, offset);
367 EXPECT_EQ(len - 1, ptr.length());
368 EXPECT_EQ(0, memcmp(ptr.c_str(), "BC\n", len - 1));
371 TEST_F(TestRawPipe, c_str_dest_short_explicit_offset) {
373 bufferptr ptr = bufferptr(buffer::create_zero_copy(2, fd, &offset));
374 EXPECT_EQ(3, offset);
375 EXPECT_EQ(2u, ptr.length());
376 EXPECT_EQ(0, memcmp(ptr.c_str(), "BC", 2));
379 TEST_F(TestRawPipe, buffer_list_read_fd_zero_copy) {
381 EXPECT_EQ(-EBADF, bl.read_fd_zero_copy(-1, len));
383 EXPECT_EQ(0, bl.read_fd_zero_copy(fd, len));
384 EXPECT_EQ(len, bl.length());
385 EXPECT_EQ(0u, bl.front().unused_tail_length());
386 EXPECT_EQ(1u, bl.get_num_buffers());
387 EXPECT_EQ(len, bl.front().raw_length());
388 EXPECT_EQ(0, memcmp(bl.c_str(), "ABC\n", len));
389 EXPECT_TRUE(bl.can_zero_copy());
392 TEST_F(TestRawPipe, buffer_list_write_fd_zero_copy) {
395 EXPECT_EQ(0, bl.read_fd_zero_copy(fd, len));
396 EXPECT_TRUE(bl.can_zero_copy());
397 int out_fd = ::open(FILENAME, O_RDWR|O_CREAT|O_TRUNC, 0600);
398 EXPECT_EQ(0, bl.write_fd_zero_copy(out_fd));
400 memset(&st, 0, sizeof(st));
401 EXPECT_EQ(0, ::stat(FILENAME, &st));
402 EXPECT_EQ(len, st.st_size);
404 EXPECT_EQ((int)len, safe_read(out_fd, buf, len + 1));
405 EXPECT_EQ(0, memcmp(buf, "ABC\n", len));
409 #endif // CEPH_HAVE_SPLICE
412 // +-----------+ +-----+
414 // | offset +----------------+ |
416 // | length +---- | |
418 // +-----------+ \---+ |
420 // +-----------+ | raw |
423 TEST(BufferPtr, constructors) {
430 EXPECT_FALSE(ptr.have_raw());
431 EXPECT_EQ((unsigned)0, ptr.offset());
432 EXPECT_EQ((unsigned)0, ptr.length());
438 bufferptr ptr(buffer::create(len));
439 EXPECT_TRUE(ptr.have_raw());
440 EXPECT_EQ((unsigned)0, ptr.offset());
441 EXPECT_EQ(len, ptr.length());
442 EXPECT_EQ(ptr.raw_length(), ptr.length());
443 EXPECT_EQ(1, ptr.raw_nref());
446 // ptr::ptr(unsigned l)
450 EXPECT_TRUE(ptr.have_raw());
451 EXPECT_EQ((unsigned)0, ptr.offset());
452 EXPECT_EQ(len, ptr.length());
453 EXPECT_EQ(1, ptr.raw_nref());
456 // ptr(const char *d, unsigned l)
459 const std::string str(len, 'X');
460 bufferptr ptr(str.c_str(), len);
461 EXPECT_TRUE(ptr.have_raw());
462 EXPECT_EQ((unsigned)0, ptr.offset());
463 EXPECT_EQ(len, ptr.length());
464 EXPECT_EQ(1, ptr.raw_nref());
465 EXPECT_EQ(0, ::memcmp(str.c_str(), ptr.c_str(), len));
471 const std::string str(len, 'X');
472 bufferptr original(str.c_str(), len);
473 bufferptr ptr(original);
474 EXPECT_TRUE(ptr.have_raw());
475 EXPECT_EQ(original.get_raw(), ptr.get_raw());
476 EXPECT_EQ(2, ptr.raw_nref());
477 EXPECT_EQ(0, ::memcmp(original.c_str(), ptr.c_str(), len));
480 // ptr(const ptr& p, unsigned o, unsigned l)
483 const std::string str(len, 'X');
484 bufferptr original(str.c_str(), len);
485 bufferptr ptr(original, 0, 0);
486 EXPECT_TRUE(ptr.have_raw());
487 EXPECT_EQ(original.get_raw(), ptr.get_raw());
488 EXPECT_EQ(2, ptr.raw_nref());
489 EXPECT_EQ(0, ::memcmp(original.c_str(), ptr.c_str(), len));
490 PrCtl unset_dumpable;
491 EXPECT_DEATH(bufferptr(original, 0, original.length() + 1), "");
492 EXPECT_DEATH(bufferptr(bufferptr(), 0, 0), "");
498 const std::string str(len, 'X');
499 bufferptr original(str.c_str(), len);
500 bufferptr ptr(std::move(original));
501 EXPECT_TRUE(ptr.have_raw());
502 EXPECT_FALSE(original.have_raw());
503 EXPECT_EQ(0, ::memcmp(str.c_str(), ptr.c_str(), len));
504 EXPECT_EQ(1, ptr.raw_nref());
508 TEST(BufferPtr, operator_assign) {
510 // ptr& operator= (const ptr& p)
513 ptr.copy_in(0, 3, "ABC");
516 bufferptr copy = ptr;
517 copy.copy_out(1, 1, dest);
518 ASSERT_EQ('B', dest[0]);
522 // ptr& operator= (ptr&& p)
524 bufferptr move = std::move(ptr);
526 move.copy_out(1, 1, dest);
527 ASSERT_EQ('B', dest[0]);
529 EXPECT_FALSE(ptr.have_raw());
532 TEST(BufferPtr, assignment) {
535 // override a bufferptr set with the same raw
538 bufferptr original(len);
539 bufferptr same_raw(original.get_raw());
541 unsigned length = len - offset;
542 original.set_offset(offset);
543 original.set_length(length);
545 ASSERT_EQ(2, original.raw_nref());
546 ASSERT_EQ(same_raw.get_raw(), original.get_raw());
547 ASSERT_EQ(same_raw.offset(), original.offset());
548 ASSERT_EQ(same_raw.length(), original.length());
552 // self assignment is a noop
555 bufferptr original(len);
557 ASSERT_EQ(1, original.raw_nref());
558 ASSERT_EQ((unsigned)0, original.offset());
559 ASSERT_EQ(len, original.length());
563 // a copy points to the same raw
566 bufferptr original(len);
568 unsigned length = len - offset;
569 original.set_offset(offset);
570 original.set_length(length);
573 ASSERT_EQ(2, original.raw_nref());
574 ASSERT_EQ(ptr.get_raw(), original.get_raw());
575 ASSERT_EQ(original.offset(), ptr.offset());
576 ASSERT_EQ(original.length(), ptr.length());
580 TEST(BufferPtr, clone) {
583 ::memset(ptr.c_str(), 'X', len);
584 bufferptr clone = ptr.clone();
585 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
588 TEST(BufferPtr, swap) {
592 ::memset(ptr1.c_str(), 'X', len);
593 unsigned ptr1_offset = 4;
594 ptr1.set_offset(ptr1_offset);
595 unsigned ptr1_length = 3;
596 ptr1.set_length(ptr1_length);
599 ::memset(ptr2.c_str(), 'Y', len);
600 unsigned ptr2_offset = 5;
601 ptr2.set_offset(ptr2_offset);
602 unsigned ptr2_length = 7;
603 ptr2.set_length(ptr2_length);
607 EXPECT_EQ(ptr2_length, ptr1.length());
608 EXPECT_EQ(ptr2_offset, ptr1.offset());
609 EXPECT_EQ('Y', ptr1[0]);
611 EXPECT_EQ(ptr1_length, ptr2.length());
612 EXPECT_EQ(ptr1_offset, ptr2.offset());
613 EXPECT_EQ('X', ptr2[0]);
616 TEST(BufferPtr, release) {
621 bufferptr ptr2(ptr1);
622 EXPECT_EQ(2, ptr1.raw_nref());
624 EXPECT_EQ(1, ptr1.raw_nref());
627 TEST(BufferPtr, have_raw) {
630 EXPECT_FALSE(ptr.have_raw());
634 EXPECT_TRUE(ptr.have_raw());
638 TEST(BufferPtr, at_buffer_head) {
640 EXPECT_TRUE(ptr.at_buffer_head());
642 EXPECT_FALSE(ptr.at_buffer_head());
645 TEST(BufferPtr, at_buffer_tail) {
647 EXPECT_TRUE(ptr.at_buffer_tail());
649 EXPECT_FALSE(ptr.at_buffer_tail());
652 TEST(BufferPtr, is_n_page_sized) {
654 bufferptr ptr(CEPH_PAGE_SIZE);
655 EXPECT_TRUE(ptr.is_n_page_sized());
659 EXPECT_FALSE(ptr.is_n_page_sized());
663 TEST(BufferPtr, is_partial) {
665 EXPECT_FALSE(a.is_partial());
667 EXPECT_FALSE(b.is_partial());
668 bufferptr c(b, 1, 9);
669 EXPECT_TRUE(c.is_partial());
670 bufferptr d(b, 0, 9);
671 EXPECT_TRUE(d.is_partial());
674 TEST(BufferPtr, accessors) {
677 ptr.c_str()[0] = 'X';
679 const bufferptr const_ptr(ptr);
681 EXPECT_NE((void*)NULL, (void*)ptr.get_raw());
682 EXPECT_EQ('X', ptr.c_str()[0]);
685 PrCtl unset_dumpable;
686 EXPECT_DEATH(ptr.c_str(), "");
687 EXPECT_DEATH(ptr[0], "");
689 EXPECT_EQ('X', const_ptr.c_str()[0]);
691 const bufferptr const_ptr;
692 PrCtl unset_dumpable;
693 EXPECT_DEATH(const_ptr.c_str(), "");
694 EXPECT_DEATH(const_ptr[0], "");
696 EXPECT_EQ(len, const_ptr.length());
697 EXPECT_EQ((unsigned)0, const_ptr.offset());
698 EXPECT_EQ((unsigned)0, const_ptr.start());
699 EXPECT_EQ(len, const_ptr.end());
700 EXPECT_EQ(len, const_ptr.end());
704 ptr.set_length(ptr.length() - unused);
705 EXPECT_EQ(unused, ptr.unused_tail_length());
709 EXPECT_EQ((unsigned)0, ptr.unused_tail_length());
712 PrCtl unset_dumpable;
713 EXPECT_DEATH(ptr[len], "");
714 EXPECT_DEATH(const_ptr[len], "");
717 const bufferptr const_ptr;
718 PrCtl unset_dumpable;
719 EXPECT_DEATH(const_ptr.raw_c_str(), "");
720 EXPECT_DEATH(const_ptr.raw_length(), "");
721 EXPECT_DEATH(const_ptr.raw_nref(), "");
723 EXPECT_NE((const char *)NULL, const_ptr.raw_c_str());
724 EXPECT_EQ(len, const_ptr.raw_length());
725 EXPECT_EQ(2, const_ptr.raw_nref());
729 ptr.set_length(ptr.length() - wasted * 2);
730 ptr.set_offset(wasted);
731 EXPECT_EQ(wasted * 2, ptr.wasted());
735 TEST(BufferPtr, cmp) {
738 bufferptr ab("AB", 2);
739 bufferptr af("AF", 2);
740 bufferptr acc("ACC", 3);
741 EXPECT_GE(-1, empty.cmp(a));
742 EXPECT_LE(1, a.cmp(empty));
743 EXPECT_GE(-1, a.cmp(ab));
744 EXPECT_LE(1, ab.cmp(a));
745 EXPECT_EQ(0, ab.cmp(ab));
746 EXPECT_GE(-1, ab.cmp(af));
747 EXPECT_LE(1, af.cmp(ab));
748 EXPECT_GE(-1, acc.cmp(af));
749 EXPECT_LE(1, af.cmp(acc));
752 TEST(BufferPtr, is_zero) {
753 char str[2] = { '\0', 'X' };
755 const bufferptr ptr(buffer::create_static(2, str));
756 EXPECT_FALSE(ptr.is_zero());
759 const bufferptr ptr(buffer::create_static(1, str));
760 EXPECT_TRUE(ptr.is_zero());
764 TEST(BufferPtr, copy_out) {
767 PrCtl unset_dumpable;
768 EXPECT_DEATH(ptr.copy_out((unsigned)0, (unsigned)0, NULL), "");
772 const bufferptr ptr(buffer::create_static(strlen(in), in));
773 EXPECT_THROW(ptr.copy_out((unsigned)0, strlen(in) + 1, NULL), buffer::end_of_buffer);
774 EXPECT_THROW(ptr.copy_out(strlen(in) + 1, (unsigned)0, NULL), buffer::end_of_buffer);
775 char out[1] = { 'X' };
776 ptr.copy_out((unsigned)1, (unsigned)1, out);
777 EXPECT_EQ('B', out[0]);
781 TEST(BufferPtr, copy_out_bench) {
782 for (int s=1; s<=8; s*=2) {
783 utime_t start = ceph_clock_now();
784 int buflen = 1048576;
787 for (int i=0; i<count; ++i) {
788 bufferptr bp(buflen);
789 for (int64_t j=0; j<buflen; j += s) {
790 bp.copy_out(j, s, (char *)&v);
793 utime_t end = ceph_clock_now();
794 cout << count << " fills of buffer len " << buflen
795 << " with " << s << " byte copy_out in"
796 << (end - start) << std::endl;
800 TEST(BufferPtr, copy_in) {
803 PrCtl unset_dumpable;
804 EXPECT_DEATH(ptr.copy_in((unsigned)0, (unsigned)0, NULL), "");
810 PrCtl unset_dumpable;
811 EXPECT_DEATH(ptr.copy_in((unsigned)0, strlen(in) + 1, NULL), "");
812 EXPECT_DEATH(ptr.copy_in(strlen(in) + 1, (unsigned)0, NULL), "");
814 ptr.copy_in((unsigned)0, (unsigned)2, in);
815 EXPECT_EQ(in[0], ptr[0]);
816 EXPECT_EQ(in[1], ptr[1]);
820 TEST(BufferPtr, copy_in_bench) {
821 for (int s=1; s<=8; s*=2) {
822 utime_t start = ceph_clock_now();
823 int buflen = 1048576;
825 for (int i=0; i<count; ++i) {
826 bufferptr bp(buflen);
827 for (int64_t j=0; j<buflen; j += s) {
828 bp.copy_in(j, s, (char *)&j, false);
831 utime_t end = ceph_clock_now();
832 cout << count << " fills of buffer len " << buflen
833 << " with " << s << " byte copy_in in "
834 << (end - start) << std::endl;
838 TEST(BufferPtr, append) {
841 PrCtl unset_dumpable;
842 EXPECT_DEATH(ptr.append('A'), "");
843 EXPECT_DEATH(ptr.append("B", (unsigned)1), "");
848 PrCtl unset_dumpable;
849 EXPECT_DEATH(ptr.append('A'), "");
850 EXPECT_DEATH(ptr.append("B", (unsigned)1), "");
854 EXPECT_EQ((unsigned)1, ptr.length());
855 EXPECT_EQ('A', ptr[0]);
856 ptr.append("B", (unsigned)1);
857 EXPECT_EQ((unsigned)2, ptr.length());
858 EXPECT_EQ('B', ptr[1]);
862 TEST(BufferPtr, append_bench) {
864 memset(src, 0, sizeof(src));
865 for (int s=4; s<=16384; s*=4) {
866 utime_t start = ceph_clock_now();
867 int buflen = 1048576;
869 for (int i=0; i<count; ++i) {
870 bufferptr bp(buflen);
872 for (int64_t j=0; j<buflen; j += s) {
876 utime_t end = ceph_clock_now();
877 cout << count << " fills of buffer len " << buflen
878 << " with " << s << " byte appends in "
879 << (end - start) << std::endl;
883 TEST(BufferPtr, zero) {
885 bufferptr ptr(buffer::create_static(strlen(str), str));
887 PrCtl unset_dumpable;
888 EXPECT_DEATH(ptr.zero(ptr.length() + 1, 0), "");
891 EXPECT_EQ('X', ptr[0]);
892 EXPECT_EQ('\0', ptr[1]);
893 EXPECT_EQ('X', ptr[2]);
895 EXPECT_EQ('\0', ptr[0]);
898 TEST(BufferPtr, ostream) {
901 std::ostringstream stream;
903 EXPECT_GT(stream.str().size(), stream.str().find("buffer:ptr(0~0 no raw"));
907 bufferptr ptr(buffer::create_static(strlen(str), str));
908 std::ostringstream stream;
910 EXPECT_GT(stream.str().size(), stream.str().find("len 4 nref 1)"));
918 // +----------+ +-----+ | | | |
919 // | append_ >-------> >--------------------> | |
920 // | buffer | +-----+ | | | |
921 // +----------+ ptr | | | |
922 // | _len | list +-----+ | | | |
923 // +----------+ +------+ ,--->+ >-----> | |
924 // | _buffers >----> >----- +-----+ | +-----+ |
925 // +----------+ +----^-+ \ ptr | raw |
926 // | last_p | / `-->+-----+ | +-----+ |
927 // +--------+-+ / + >-----> | |
928 // | ,- ,--->+-----+ | | | |
931 // +-v--+-^--+--^+-------+ | | | |
932 // | bl | ls | p | p_off >--------------->| | |
933 // +----+----+-----+-----+ | +-----+ |
934 // | | off >------------->| raw |
935 // +---------------+-----+ | |
936 // iterator +---------+
938 TEST(BufferListIterator, constructors) {
943 buffer::list::iterator i;
944 EXPECT_EQ((unsigned)0, i.get_off());
948 // iterator(list *l, unsigned o=0)
955 bufferlist::iterator i(&bl);
956 EXPECT_EQ((unsigned)0, i.get_off());
960 bufferlist::iterator i(&bl, 1);
962 EXPECT_EQ((unsigned)2, i.get_remaining());
967 // iterator(list *l, unsigned o, std::list<ptr>::iterator ip, unsigned po)
968 // not tested because of http://tracker.ceph.com/issues/4101
971 // iterator(const iterator& other)
976 bufferlist::iterator i(&bl, 1);
977 bufferlist::iterator j(i);
989 // const_iterator(const iterator& other)
994 bufferlist::iterator i(&bl);
995 bufferlist::const_iterator ci(i);
996 EXPECT_EQ(0u, ci.get_off());
1001 TEST(BufferListIterator, empty_create_append_copy) {
1002 bufferlist bl, bl2, bl3, out;
1009 ASSERT_TRUE(out.contents_equal(bl));
1012 TEST(BufferListIterator, operator_assign) {
1014 bl.append("ABC", 3);
1015 bufferlist::iterator i(&bl, 1);
1019 bufferlist::iterator j;
1024 TEST(BufferListIterator, get_off) {
1026 bl.append("ABC", 3);
1027 bufferlist::iterator i(&bl, 1);
1028 EXPECT_EQ((unsigned)1, i.get_off());
1031 TEST(BufferListIterator, get_remaining) {
1033 bl.append("ABC", 3);
1034 bufferlist::iterator i(&bl, 1);
1035 EXPECT_EQ((unsigned)2, i.get_remaining());
1038 TEST(BufferListIterator, end) {
1041 bufferlist::iterator i(&bl);
1042 EXPECT_TRUE(i.end());
1044 bl.append("ABC", 3);
1046 bufferlist::iterator i(&bl);
1047 EXPECT_FALSE(i.end());
1051 TEST(BufferListIterator, advance) {
1053 const std::string one("ABC");
1054 bl.append(bufferptr(one.c_str(), one.size()));
1055 const std::string two("DEF");
1056 bl.append(bufferptr(two.c_str(), two.size()));
1059 bufferlist::iterator i(&bl);
1060 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1063 bufferlist::iterator i(&bl);
1064 EXPECT_THROW(i.advance(-1), buffer::end_of_buffer);
1067 bufferlist::iterator i(&bl);
1080 TEST(BufferListIterator, get_ptr_and_advance)
1082 bufferptr a("one", 3);
1083 bufferptr b("two", 3);
1084 bufferptr c("three", 5);
1090 bufferlist::iterator p = bl.begin();
1091 ASSERT_EQ(3u, p.get_ptr_and_advance(11, &ptr));
1092 ASSERT_EQ(bl.length() - 3u, p.get_remaining());
1093 ASSERT_EQ(0, memcmp(ptr, "one", 3));
1094 ASSERT_EQ(2u, p.get_ptr_and_advance(2, &ptr));
1095 ASSERT_EQ(0, memcmp(ptr, "tw", 2));
1096 ASSERT_EQ(1u, p.get_ptr_and_advance(4, &ptr));
1097 ASSERT_EQ(0, memcmp(ptr, "o", 1));
1098 ASSERT_EQ(5u, p.get_ptr_and_advance(5, &ptr));
1099 ASSERT_EQ(0, memcmp(ptr, "three", 5));
1100 ASSERT_EQ(0u, p.get_remaining());
1103 TEST(BufferListIterator, iterator_crc32c) {
1108 string s1(100, 'a');
1118 bufferlist::iterator it = bl2.begin();
1119 ASSERT_EQ(bl1.crc32c(0), it.crc32c(it.get_remaining(), 0));
1120 ASSERT_EQ(0u, it.get_remaining());
1123 ASSERT_EQ(bl2.crc32c(0), it.crc32c(it.get_remaining(), 0));
1125 bl3.append(s.substr(98, 55));
1128 ASSERT_EQ(bl3.crc32c(0), it.crc32c(55, 0));
1129 ASSERT_EQ(4u, it.get_remaining());
1132 bl3.append(s.substr(98 + 55));
1134 it.advance(98 + 55);
1135 ASSERT_EQ(bl3.crc32c(0), it.crc32c(10, 0));
1136 ASSERT_EQ(0u, it.get_remaining());
1139 TEST(BufferListIterator, seek) {
1141 bl.append("ABC", 3);
1142 bufferlist::iterator i(&bl, 1);
1148 TEST(BufferListIterator, operator_star) {
1151 bufferlist::iterator i(&bl);
1152 EXPECT_THROW(*i, buffer::end_of_buffer);
1154 bl.append("ABC", 3);
1156 bufferlist::iterator i(&bl);
1158 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1159 EXPECT_THROW(*i, buffer::end_of_buffer);
1163 TEST(BufferListIterator, operator_equal) {
1165 bl.append("ABC", 3);
1167 bufferlist::iterator i(&bl);
1168 bufferlist::iterator j(&bl);
1172 bufferlist::const_iterator ci = bl.begin();
1173 bufferlist::iterator i = bl.begin();
1179 TEST(BufferListIterator, operator_nequal) {
1181 bl.append("ABC", 3);
1183 bufferlist::iterator i(&bl);
1184 bufferlist::iterator j(&bl);
1188 bufferlist::const_iterator ci = bl.begin();
1189 bufferlist::const_iterator cj = bl.begin();
1192 bufferlist::iterator i = bl.begin();
1197 // tests begin(), end(), operator++() also
1201 EXPECT_EQ(s[i++], c);
1206 TEST(BufferListIterator, operator_plus_plus) {
1209 bufferlist::iterator i(&bl);
1210 EXPECT_THROW(++i, buffer::end_of_buffer);
1212 bl.append("ABC", 3);
1214 bufferlist::iterator i(&bl);
1220 TEST(BufferListIterator, get_current_ptr) {
1223 bufferlist::iterator i(&bl);
1224 EXPECT_THROW(++i, buffer::end_of_buffer);
1226 bl.append("ABC", 3);
1228 bufferlist::iterator i(&bl, 1);
1229 const buffer::ptr ptr = i.get_current_ptr();
1230 EXPECT_EQ('B', ptr[0]);
1231 EXPECT_EQ((unsigned)1, ptr.offset());
1232 EXPECT_EQ((unsigned)2, ptr.length());
1236 TEST(BufferListIterator, copy) {
1238 const char *expected = "ABC";
1239 bl.append(expected, 3);
1241 // void copy(unsigned len, char *dest);
1244 char* copy = (char*)malloc(3);
1245 ::memset(copy, 'X', 3);
1246 bufferlist::iterator i(&bl);
1248 // demonstrates that it seeks back to offset if p == ls->end()
1250 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1252 EXPECT_EQ(0, ::memcmp(copy, expected, 2));
1253 EXPECT_EQ('X', copy[2]);
1256 EXPECT_EQ(0, ::memcmp(copy, expected, 3));
1259 // void buffer::list::iterator::copy_deep(unsigned len, ptr &dest)
1263 bufferlist::iterator i(&bl);
1264 i.copy_deep(2, ptr);
1265 EXPECT_EQ((unsigned)2, ptr.length());
1266 EXPECT_EQ('A', ptr[0]);
1267 EXPECT_EQ('B', ptr[1]);
1270 // void buffer::list::iterator::copy_shallow(unsigned len, ptr &dest)
1274 bufferlist::iterator i(&bl);
1275 i.copy_shallow(2, ptr);
1276 EXPECT_EQ((unsigned)2, ptr.length());
1277 EXPECT_EQ('A', ptr[0]);
1278 EXPECT_EQ('B', ptr[1]);
1281 // void buffer::list::iterator::copy(unsigned len, list &dest)
1285 bufferlist::iterator i(&bl);
1287 // demonstrates that it seeks back to offset if p == ls->end()
1289 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1291 EXPECT_EQ(0, ::memcmp(copy.c_str(), expected, 2));
1294 EXPECT_EQ('A', copy[0]);
1295 EXPECT_EQ('B', copy[1]);
1296 EXPECT_EQ('A', copy[2]);
1297 EXPECT_EQ('B', copy[3]);
1298 EXPECT_EQ('C', copy[4]);
1299 EXPECT_EQ((unsigned)(2 + 3), copy.length());
1302 // void buffer::list::iterator::copy_all(list &dest)
1306 bufferlist::iterator i(&bl);
1308 // demonstrates that it seeks back to offset if p == ls->end()
1310 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1312 EXPECT_EQ('A', copy[0]);
1313 EXPECT_EQ('B', copy[1]);
1314 EXPECT_EQ('C', copy[2]);
1315 EXPECT_EQ((unsigned)3, copy.length());
1318 // void copy(unsigned len, std::string &dest)
1322 bufferlist::iterator i(&bl);
1324 // demonstrates that it seeks back to offset if p == ls->end()
1326 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1328 EXPECT_EQ(0, ::memcmp(copy.c_str(), expected, 2));
1331 EXPECT_EQ('A', copy[0]);
1332 EXPECT_EQ('B', copy[1]);
1333 EXPECT_EQ('A', copy[2]);
1334 EXPECT_EQ('B', copy[3]);
1335 EXPECT_EQ('C', copy[4]);
1336 EXPECT_EQ((unsigned)(2 + 3), copy.length());
1340 TEST(BufferListIterator, copy_in) {
1342 const char *existing = "XXX";
1343 bl.append(existing, 3);
1345 // void buffer::list::iterator::copy_in(unsigned len, const char *src)
1348 bufferlist::iterator i(&bl);
1350 // demonstrates that it seeks back to offset if p == ls->end()
1352 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1353 const char *expected = "ABC";
1354 i.copy_in(3, expected);
1355 EXPECT_EQ(0, ::memcmp(bl.c_str(), expected, 3));
1356 EXPECT_EQ('A', bl[0]);
1357 EXPECT_EQ('B', bl[1]);
1358 EXPECT_EQ('C', bl[2]);
1359 EXPECT_EQ((unsigned)3, bl.length());
1362 // void buffer::list::iterator::copy_in(unsigned len, const list& otherl)
1365 bufferlist::iterator i(&bl);
1367 // demonstrates that it seeks back to offset if p == ls->end()
1369 EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
1370 bufferlist expected;
1371 expected.append("ABC", 3);
1372 i.copy_in(3, expected);
1373 EXPECT_EQ(0, ::memcmp(bl.c_str(), expected.c_str(), 3));
1374 EXPECT_EQ('A', bl[0]);
1375 EXPECT_EQ('B', bl[1]);
1376 EXPECT_EQ('C', bl[2]);
1377 EXPECT_EQ((unsigned)3, bl.length());
1381 // iterator& buffer::list::const_iterator::operator++()
1382 TEST(BufferListConstIterator, operator_plus_plus) {
1385 bufferlist::const_iterator i(&bl);
1386 EXPECT_THROW(++i, buffer::end_of_buffer);
1388 bl.append("ABC", 3);
1390 const bufferlist const_bl(bl);
1391 bufferlist::const_iterator i(const_bl.begin());
1398 TEST(BufferList, constructors) {
1404 ASSERT_EQ((unsigned)0, bl.length());
1407 // list(unsigned prealloc)
1411 ASSERT_EQ((unsigned)0, bl.length());
1413 ASSERT_EQ('A', bl[0]);
1416 // list(const list& other)
1421 ASSERT_EQ('A', bl[0]);
1422 bufferlist copy(bl);
1423 ASSERT_EQ('A', copy[0]);
1426 // list(list&& other)
1431 bufferlist copy = std::move(bl);
1432 ASSERT_EQ(0U, bl.length());
1433 ASSERT_EQ(1U, copy.length());
1434 ASSERT_EQ('A', copy[0]);
1438 void bench_bufferlist_alloc(int size, int num, int per)
1440 utime_t start = ceph_clock_now();
1441 for (int i=0; i<num; ++i) {
1443 for (int j=0; j<per; ++j)
1444 bl.append(buffer::create(size));
1446 utime_t end = ceph_clock_now();
1447 cout << num << " alloc of size " << size
1448 << " in " << (end - start) << std::endl;
1451 TEST(BufferList, BenchAlloc) {
1452 bench_bufferlist_alloc(32768, 100000, 16);
1453 bench_bufferlist_alloc(25000, 100000, 16);
1454 bench_bufferlist_alloc(16384, 100000, 16);
1455 bench_bufferlist_alloc(10000, 100000, 16);
1456 bench_bufferlist_alloc(8192, 100000, 16);
1457 bench_bufferlist_alloc(6000, 100000, 16);
1458 bench_bufferlist_alloc(4096, 100000, 16);
1459 bench_bufferlist_alloc(1024, 100000, 16);
1460 bench_bufferlist_alloc(256, 100000, 16);
1461 bench_bufferlist_alloc(32, 100000, 16);
1462 bench_bufferlist_alloc(4, 100000, 16);
1465 TEST(BufferList, operator_equal) {
1467 // list& operator= (const list& other)
1470 bl.append("ABC", 3);
1473 bl.copy(1, 1, dest);
1474 ASSERT_EQ('B', dest[0]);
1477 bufferlist copy = bl;
1479 copy.copy(1, 1, dest);
1480 ASSERT_EQ('B', dest[0]);
1484 // list& operator= (list&& other)
1486 bufferlist move = std::move(bl);
1489 move.copy(1, 1, dest);
1490 ASSERT_EQ('B', dest[0]);
1492 EXPECT_TRUE(move.length());
1493 EXPECT_TRUE(!bl.length());
1496 TEST(BufferList, buffers) {
1498 ASSERT_EQ((unsigned)0, bl.get_num_buffers());
1500 ASSERT_EQ((unsigned)1, bl.get_num_buffers());
1503 TEST(BufferList, to_str) {
1507 ASSERT_EQ(bl.to_str(), string("foo"));
1510 bufferptr a("foobarbaz", 9);
1511 bufferptr b("123456789", 9);
1512 bufferptr c("ABCDEFGHI", 9);
1517 ASSERT_EQ(bl.to_str(), string("foobarbaz123456789ABCDEFGHI"));
1521 TEST(BufferList, get_contiguous) {
1523 bufferptr a("foobarbaz", 9);
1524 bufferptr b("123456789", 9);
1525 bufferptr c("ABCDEFGHI", 9);
1527 ASSERT_EQ(0, bl.get_contiguous(0, 0));
1532 ASSERT_EQ(3u, bl.get_num_buffers());
1533 ASSERT_EQ(0, memcmp("bar", bl.get_contiguous(3, 3), 3));
1534 ASSERT_EQ(0, memcmp("456", bl.get_contiguous(12, 3), 3));
1535 ASSERT_EQ(0, memcmp("ABC", bl.get_contiguous(18, 3), 3));
1536 ASSERT_EQ(3u, bl.get_num_buffers());
1537 ASSERT_EQ(0, memcmp("789ABC", bl.get_contiguous(15, 6), 6));
1538 ASSERT_EQ(2u, bl.get_num_buffers());
1542 bufferptr a("foobarbaz", 9);
1543 bufferptr b("123456789", 9);
1544 bufferptr c("ABCDEFGHI", 9);
1551 ASSERT_EQ(0, memcmp("789ABCDEFGHI", bl.get_contiguous(15, 12), 12));
1552 ASSERT_EQ(2u, bl.get_num_buffers());
1556 bufferptr a("foobarbaz", 9);
1557 bufferptr b("123456789", 9);
1558 bufferptr c("ABCDEFGHI", 9);
1565 ASSERT_EQ(0, memcmp("z123456789AB", bl.get_contiguous(8, 12), 12));
1566 ASSERT_EQ(1u, bl.get_num_buffers());
1570 TEST(BufferList, swap) {
1581 ASSERT_EQ('B', s1[0]);
1585 ASSERT_EQ('A', s2[0]);
1588 TEST(BufferList, length) {
1590 ASSERT_EQ((unsigned)0, bl.length());
1592 ASSERT_EQ((unsigned)1, bl.length());
1595 TEST(BufferList, contents_equal) {
1604 ASSERT_FALSE(bl1.contents_equal(bl2)); // different length
1607 ASSERT_TRUE(bl1.contents_equal(bl2)); // same length same content
1613 ASSERT_FALSE(bl1.contents_equal(bl3)); // same length different content
1616 TEST(BufferList, is_aligned) {
1617 const int SIMD_ALIGN = 32;
1620 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1624 bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
1628 EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
1629 bl.rebuild_aligned(SIMD_ALIGN);
1630 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1634 bufferptr ptr(buffer::create_aligned(SIMD_ALIGN + 1, SIMD_ALIGN));
1636 ptr.set_length(SIMD_ALIGN);
1638 EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
1639 bl.rebuild_aligned(SIMD_ALIGN);
1640 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1644 TEST(BufferList, is_n_align_sized) {
1645 const int SIMD_ALIGN = 32;
1648 EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
1653 EXPECT_FALSE(bl.is_n_align_sized(SIMD_ALIGN));
1657 bl.append_zero(SIMD_ALIGN);
1658 EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
1662 TEST(BufferList, is_page_aligned) {
1665 EXPECT_TRUE(bl.is_page_aligned());
1669 bufferptr ptr(buffer::create_page_aligned(2));
1673 EXPECT_FALSE(bl.is_page_aligned());
1674 bl.rebuild_page_aligned();
1675 EXPECT_TRUE(bl.is_page_aligned());
1679 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
1681 ptr.set_length(CEPH_PAGE_SIZE);
1683 EXPECT_FALSE(bl.is_page_aligned());
1684 bl.rebuild_page_aligned();
1685 EXPECT_TRUE(bl.is_page_aligned());
1689 TEST(BufferList, is_n_page_sized) {
1692 EXPECT_TRUE(bl.is_n_page_sized());
1697 EXPECT_FALSE(bl.is_n_page_sized());
1701 bl.append_zero(CEPH_PAGE_SIZE);
1702 EXPECT_TRUE(bl.is_n_page_sized());
1706 TEST(BufferList, page_aligned_appender) {
1708 auto a = bl.get_page_aligned_appender(5);
1709 a.append("asdf", 4);
1711 cout << bl << std::endl;
1712 ASSERT_EQ(1u, bl.get_num_buffers());
1713 a.append("asdf", 4);
1714 for (unsigned n = 0; n < 3 * CEPH_PAGE_SIZE; ++n) {
1718 cout << bl << std::endl;
1719 ASSERT_EQ(1u, bl.get_num_buffers());
1720 for (unsigned n = 0; n < 3 * CEPH_PAGE_SIZE; ++n) {
1724 cout << bl << std::endl;
1725 ASSERT_EQ(2u, bl.get_num_buffers());
1726 for (unsigned n = 0; n < 10 * CEPH_PAGE_SIZE; ++n) {
1727 a.append("asdfasdfasdf", 1);
1730 cout << bl << std::endl;
1733 TEST(BufferList, rebuild_aligned_size_and_memory) {
1734 const unsigned SIMD_ALIGN = 32;
1735 const unsigned BUFFER_SIZE = 67;
1738 // These two must be concatenated into one memory + size aligned
1741 bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
1747 bufferptr ptr(buffer::create_aligned(BUFFER_SIZE - 1, SIMD_ALIGN));
1750 // This one must be left alone
1752 bufferptr ptr(buffer::create_aligned(BUFFER_SIZE, SIMD_ALIGN));
1755 // These two must be concatenated into one memory + size aligned
1758 bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
1764 bufferptr ptr(buffer::create_aligned(BUFFER_SIZE - 1, SIMD_ALIGN));
1767 EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
1768 EXPECT_FALSE(bl.is_n_align_sized(BUFFER_SIZE));
1769 EXPECT_EQ(BUFFER_SIZE * 3, bl.length());
1770 EXPECT_FALSE(bl.front().is_aligned(SIMD_ALIGN));
1771 EXPECT_FALSE(bl.front().is_n_align_sized(BUFFER_SIZE));
1772 EXPECT_EQ(5U, bl.get_num_buffers());
1773 bl.rebuild_aligned_size_and_memory(BUFFER_SIZE, SIMD_ALIGN);
1774 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1775 EXPECT_TRUE(bl.is_n_align_sized(BUFFER_SIZE));
1776 EXPECT_EQ(3U, bl.get_num_buffers());
1779 TEST(BufferList, is_zero) {
1782 EXPECT_TRUE(bl.is_zero());
1787 EXPECT_FALSE(bl.is_zero());
1792 EXPECT_TRUE(bl.is_zero());
1795 for (size_t i = 1; i <= 256; ++i) {
1798 EXPECT_TRUE(bl.is_zero());
1800 // ensure buffer is a single, contiguous before testing
1802 EXPECT_FALSE(bl.is_zero());
1807 TEST(BufferList, clear) {
1810 bl.append_zero(len);
1812 EXPECT_EQ((unsigned)0, bl.length());
1813 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1816 TEST(BufferList, push_front) {
1818 // void push_front(ptr& bp)
1824 EXPECT_EQ((unsigned)0, bl.length());
1825 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1832 ptr.c_str()[0] = 'B';
1834 EXPECT_EQ((unsigned)(1 + len), bl.length());
1835 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1836 EXPECT_EQ('B', bl.front()[0]);
1837 EXPECT_EQ(ptr.get_raw(), bl.front().get_raw());
1840 // void push_front(raw *r)
1846 ptr.c_str()[0] = 'B';
1847 bl.push_front(ptr.get_raw());
1848 EXPECT_EQ((unsigned)(1 + len), bl.length());
1849 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1850 EXPECT_EQ('B', bl.front()[0]);
1851 EXPECT_EQ(ptr.get_raw(), bl.front().get_raw());
1854 // void push_front(ptr&& bp)
1859 bl.push_front(std::move(ptr));
1860 EXPECT_EQ((unsigned)0, bl.length());
1861 EXPECT_EQ((unsigned)0, bl.buffers().size());
1867 ptr.c_str()[0] = 'B';
1868 bl.push_front(std::move(ptr));
1869 EXPECT_EQ((unsigned)(1 + len), bl.length());
1870 EXPECT_EQ((unsigned)2, bl.buffers().size());
1871 EXPECT_EQ('B', bl.buffers().front()[0]);
1872 EXPECT_FALSE(ptr.get_raw());
1876 TEST(BufferList, push_back) {
1878 // void push_back(ptr& bp)
1884 EXPECT_EQ((unsigned)0, bl.length());
1885 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1892 ptr.c_str()[0] = 'B';
1894 EXPECT_EQ((unsigned)(1 + len), bl.length());
1895 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1896 EXPECT_EQ('B', bl.back()[0]);
1897 EXPECT_EQ(ptr.get_raw(), bl.back().get_raw());
1900 // void push_back(raw *r)
1906 ptr.c_str()[0] = 'B';
1907 bl.push_back(ptr.get_raw());
1908 EXPECT_EQ((unsigned)(1 + len), bl.length());
1909 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1910 EXPECT_EQ('B', bl.back()[0]);
1911 EXPECT_EQ(ptr.get_raw(), bl.back().get_raw());
1914 // void push_back(ptr&& bp)
1919 bl.push_back(std::move(ptr));
1920 EXPECT_EQ((unsigned)0, bl.length());
1921 EXPECT_EQ((unsigned)0, bl.buffers().size());
1927 ptr.c_str()[0] = 'B';
1928 bl.push_back(std::move(ptr));
1929 EXPECT_EQ((unsigned)(1 + len), bl.length());
1930 EXPECT_EQ((unsigned)2, bl.buffers().size());
1931 EXPECT_EQ('B', bl.buffers().back()[0]);
1932 EXPECT_FALSE(ptr.get_raw());
1936 TEST(BufferList, is_contiguous) {
1938 EXPECT_TRUE(bl.is_contiguous());
1939 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1941 EXPECT_TRUE(bl.is_contiguous());
1942 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1945 EXPECT_FALSE(bl.is_contiguous());
1946 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1949 TEST(BufferList, rebuild) {
1952 bufferptr ptr(buffer::create_page_aligned(2));
1958 EXPECT_FALSE(bl.is_page_aligned());
1960 EXPECT_EQ(1U, bl.length());
1961 EXPECT_EQ('Y', *bl.begin());
1965 const std::string str(CEPH_PAGE_SIZE, 'X');
1966 bl.append(str.c_str(), str.size());
1967 bl.append(str.c_str(), str.size());
1968 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1969 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1971 EXPECT_TRUE(bl.is_page_aligned());
1972 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1981 EXPECT_EQ((unsigned)1, bl.length());
1982 bufferlist::iterator p = bl.begin();
1985 EXPECT_EQ(0, memcmp(dst, "X", 1));
1989 TEST(BufferList, rebuild_page_aligned) {
1993 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
1995 ptr.set_length(CEPH_PAGE_SIZE);
1998 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1999 EXPECT_FALSE(bl.is_page_aligned());
2000 bl.rebuild_page_aligned();
2001 EXPECT_TRUE(bl.is_page_aligned());
2002 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2006 bufferptr ptr(buffer::create_page_aligned(1));
2007 char *p = ptr.c_str();
2009 bl.rebuild_page_aligned();
2010 EXPECT_EQ(p, bl.front().c_str());
2015 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE));
2016 EXPECT_TRUE(ptr.is_page_aligned());
2017 EXPECT_TRUE(ptr.is_n_page_sized());
2021 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
2022 EXPECT_TRUE(ptr.is_page_aligned());
2023 EXPECT_FALSE(ptr.is_n_page_sized());
2027 bufferptr ptr(buffer::create_page_aligned(2));
2030 EXPECT_FALSE(ptr.is_page_aligned());
2031 EXPECT_FALSE(ptr.is_n_page_sized());
2035 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE - 2));
2036 EXPECT_TRUE(ptr.is_page_aligned());
2037 EXPECT_FALSE(ptr.is_n_page_sized());
2041 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE));
2042 EXPECT_TRUE(ptr.is_page_aligned());
2043 EXPECT_TRUE(ptr.is_n_page_sized());
2047 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
2049 ptr.set_length(CEPH_PAGE_SIZE);
2050 EXPECT_FALSE(ptr.is_page_aligned());
2051 EXPECT_TRUE(ptr.is_n_page_sized());
2054 EXPECT_EQ((unsigned)6, bl.get_num_buffers());
2055 EXPECT_TRUE((bl.length() & ~CEPH_PAGE_MASK) == 0);
2056 EXPECT_FALSE(bl.is_page_aligned());
2057 bl.rebuild_page_aligned();
2058 EXPECT_TRUE(bl.is_page_aligned());
2059 EXPECT_EQ((unsigned)4, bl.get_num_buffers());
2063 TEST(BufferList, claim) {
2074 EXPECT_EQ((unsigned)4, to.length());
2075 EXPECT_EQ((unsigned)1, to.get_num_buffers());
2077 EXPECT_EQ((unsigned)2, to.length());
2078 EXPECT_EQ((unsigned)1, to.get_num_buffers());
2079 EXPECT_EQ((unsigned)0, from.get_num_buffers());
2080 EXPECT_EQ((unsigned)0, from.length());
2083 TEST(BufferList, claim_append) {
2094 EXPECT_EQ((unsigned)4, to.length());
2095 EXPECT_EQ((unsigned)1, to.get_num_buffers());
2096 to.claim_append(from);
2097 EXPECT_EQ((unsigned)(4 + 2), to.length());
2098 EXPECT_EQ((unsigned)4, to.front().length());
2099 EXPECT_EQ((unsigned)2, to.back().length());
2100 EXPECT_EQ((unsigned)2, to.get_num_buffers());
2101 EXPECT_EQ((unsigned)0, from.get_num_buffers());
2102 EXPECT_EQ((unsigned)0, from.length());
2105 TEST(BufferList, claim_prepend) {
2116 EXPECT_EQ((unsigned)4, to.length());
2117 EXPECT_EQ((unsigned)1, to.get_num_buffers());
2118 to.claim_prepend(from);
2119 EXPECT_EQ((unsigned)(2 + 4), to.length());
2120 EXPECT_EQ((unsigned)2, to.front().length());
2121 EXPECT_EQ((unsigned)4, to.back().length());
2122 EXPECT_EQ((unsigned)2, to.get_num_buffers());
2123 EXPECT_EQ((unsigned)0, from.get_num_buffers());
2124 EXPECT_EQ((unsigned)0, from.length());
2127 TEST(BufferList, claim_append_piecewise) {
2128 bufferlist bl, t, dst;
2129 auto a = bl.get_page_aligned_appender(4);
2130 for (uint32_t i = 0; i < (CEPH_PAGE_SIZE + CEPH_PAGE_SIZE - 1333); i++)
2133 const char *p = bl.c_str();
2136 for (uint32_t i = 0; i < (CEPH_PAGE_SIZE + 1333); i++)
2141 EXPECT_FALSE(t.is_aligned_size_and_memory(CEPH_PAGE_SIZE, CEPH_PAGE_SIZE));
2142 dst.claim_append_piecewise(t);
2143 EXPECT_TRUE(dst.is_aligned_size_and_memory(CEPH_PAGE_SIZE, CEPH_PAGE_SIZE));
2144 const char *p1 = dst.c_str();
2145 EXPECT_TRUE(p == p1);
2148 TEST(BufferList, begin) {
2151 bufferlist::iterator i = bl.begin();
2155 TEST(BufferList, end) {
2158 bufferlist::iterator i = bl.end();
2163 TEST(BufferList, copy) {
2165 // void copy(unsigned off, unsigned len, char *dest) const;
2169 EXPECT_THROW(bl.copy((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer);
2170 const char *expected = "ABC";
2171 bl.append(expected);
2172 char *dest = new char[2];
2173 bl.copy(1, 2, dest);
2174 EXPECT_EQ(0, ::memcmp(expected + 1, dest, 2));
2178 // void copy(unsigned off, unsigned len, list &dest) const;
2183 EXPECT_THROW(bl.copy((unsigned)100, (unsigned)100, dest), buffer::end_of_buffer);
2184 const char *expected = "ABC";
2185 bl.append(expected);
2186 bl.copy(1, 2, dest);
2187 EXPECT_EQ(0, ::memcmp(expected + 1, dest.c_str(), 2));
2190 // void copy(unsigned off, unsigned len, std::string &dest) const;
2195 EXPECT_THROW(bl.copy((unsigned)100, (unsigned)100, dest), buffer::end_of_buffer);
2196 const char *expected = "ABC";
2197 bl.append(expected);
2198 bl.copy(1, 2, dest);
2199 EXPECT_EQ(0, ::memcmp(expected + 1, dest.c_str(), 2));
2203 TEST(BufferList, copy_in) {
2205 // void copy_in(unsigned off, unsigned len, const char *src);
2210 EXPECT_THROW(bl.copy_in((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer);
2211 bl.copy_in(1, 2, "AB");
2212 EXPECT_EQ(0, ::memcmp("XAB", bl.c_str(), 3));
2215 // void copy_in(unsigned off, unsigned len, const list& src);
2222 EXPECT_THROW(bl.copy_in((unsigned)100, (unsigned)100, src), buffer::end_of_buffer);
2223 bl.copy_in(1, 2, src);
2224 EXPECT_EQ(0, ::memcmp("XAB", bl.c_str(), 3));
2228 TEST(BufferList, append) {
2230 // void append(char c);
2234 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2236 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2237 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
2240 // void append(const char *data, unsigned len);
2243 bufferlist bl(CEPH_PAGE_SIZE);
2244 std::string str(CEPH_PAGE_SIZE * 2, 'X');
2245 bl.append(str.c_str(), str.size());
2246 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2247 EXPECT_EQ(CEPH_PAGE_SIZE, bl.front().length());
2248 EXPECT_EQ(CEPH_PAGE_SIZE, bl.back().length());
2251 // void append(const std::string& s);
2254 bufferlist bl(CEPH_PAGE_SIZE);
2255 std::string str(CEPH_PAGE_SIZE * 2, 'X');
2257 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2258 EXPECT_EQ(CEPH_PAGE_SIZE, bl.front().length());
2259 EXPECT_EQ(CEPH_PAGE_SIZE, bl.back().length());
2262 // void append(const ptr& bp);
2266 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2267 EXPECT_EQ((unsigned)0, bl.length());
2271 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2272 EXPECT_EQ((unsigned)0, bl.length());
2277 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2278 EXPECT_EQ((unsigned)3, bl.length());
2282 // void append(const ptr& bp, unsigned off, unsigned len);
2287 bufferptr back(bl.back());
2289 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2290 EXPECT_EQ((unsigned)1, bl.length());
2292 PrCtl unset_dumpable;
2293 EXPECT_DEATH(bl.append(in, (unsigned)100, (unsigned)100), "");
2295 EXPECT_LT((unsigned)0, in.unused_tail_length());
2297 bl.append(in, back.end(), 1);
2298 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2299 EXPECT_EQ((unsigned)2, bl.length());
2300 EXPECT_EQ('B', bl[1]);
2304 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2305 EXPECT_EQ((unsigned)0, bl.length());
2308 ptr.append("AB", 2);
2309 bl.append(ptr, 1, 1);
2310 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2311 EXPECT_EQ((unsigned)1, bl.length());
2314 // void append(const list& bl);
2322 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2323 EXPECT_EQ('B', bl[1]);
2326 // void append(std::istream& in);
2330 std::string expected("ABC\nDEF\n");
2331 std::istringstream is("ABC\n\nDEF");
2333 EXPECT_EQ(0, ::memcmp(expected.c_str(), bl.c_str(), expected.size()));
2334 EXPECT_EQ(expected.size(), bl.length());
2337 // void append(ptr&& bp);
2341 EXPECT_EQ((unsigned)0, bl.buffers().size());
2342 EXPECT_EQ((unsigned)0, bl.length());
2345 bl.append(std::move(ptr));
2346 EXPECT_EQ((unsigned)0, bl.buffers().size());
2347 EXPECT_EQ((unsigned)0, bl.length());
2351 bl.append(std::move(ptr));
2352 EXPECT_EQ((unsigned)1, bl.buffers().size());
2353 EXPECT_EQ((unsigned)3, bl.length());
2354 EXPECT_FALSE(ptr.get_raw());
2359 TEST(BufferList, append_zero) {
2362 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2363 EXPECT_EQ((unsigned)1, bl.length());
2365 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2366 EXPECT_EQ((unsigned)2, bl.length());
2367 EXPECT_EQ('\0', bl[1]);
2370 TEST(BufferList, operator_brackets) {
2372 EXPECT_THROW(bl[1], buffer::end_of_buffer);
2377 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2378 EXPECT_EQ('B', bl[1]);
2381 TEST(BufferList, c_str) {
2383 EXPECT_EQ((const char*)NULL, bl.c_str());
2388 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2389 EXPECT_EQ(0, ::memcmp("AB", bl.c_str(), 2));
2392 TEST(BufferList, substr_of) {
2394 EXPECT_THROW(bl.substr_of(bl, 1, 1), buffer::end_of_buffer);
2401 for (unsigned i = 0; i < 4; i++) {
2402 bufferptr ptr(s[i], strlen(s[i]));
2405 EXPECT_EQ((unsigned)4, bl.get_num_buffers());
2408 other.append("TO BE CLEARED");
2409 other.substr_of(bl, 4, 4);
2410 EXPECT_EQ((unsigned)2, other.get_num_buffers());
2411 EXPECT_EQ((unsigned)4, other.length());
2412 EXPECT_EQ(0, ::memcmp("EFGH", other.c_str(), 4));
2415 TEST(BufferList, splice) {
2417 EXPECT_THROW(bl.splice(1, 1), buffer::end_of_buffer);
2424 for (unsigned i = 0; i < 4; i++) {
2425 bufferptr ptr(s[i], strlen(s[i]));
2428 EXPECT_EQ((unsigned)4, bl.get_num_buffers());
2433 bl.splice(4, 4, &other);
2434 EXPECT_EQ((unsigned)3, other.get_num_buffers());
2435 EXPECT_EQ((unsigned)5, other.length());
2436 EXPECT_EQ(0, ::memcmp("XEFGH", other.c_str(), other.length()));
2437 EXPECT_EQ((unsigned)8, bl.length());
2440 EXPECT_EQ(0, ::memcmp("ABCDIJKL", tmp.c_str(), tmp.length()));
2444 EXPECT_EQ((unsigned)4, bl.length());
2445 EXPECT_EQ(0, ::memcmp("ABCD", bl.c_str(), bl.length()));
2449 bufferptr ptr1("0123456789", 10);
2451 bufferptr ptr2("abcdefghij", 10);
2452 bl.append(ptr2, 5, 5);
2454 bl.splice(10, 4, &other);
2455 EXPECT_EQ((unsigned)11, bl.length());
2456 EXPECT_EQ(0, ::memcmp("fghi", other.c_str(), other.length()));
2460 TEST(BufferList, write) {
2461 std::ostringstream stream;
2464 bl.write(1, 2, stream);
2465 EXPECT_EQ("BC", stream.str());
2468 TEST(BufferList, encode_base64) {
2472 bl.encode_base64(other);
2473 const char *expected = "QUJDRA==";
2474 EXPECT_EQ(0, ::memcmp(expected, other.c_str(), strlen(expected)));
2477 TEST(BufferList, decode_base64) {
2479 bl.append("QUJDRA==");
2481 other.decode_base64(bl);
2482 const char *expected = "ABCD";
2483 EXPECT_EQ(0, ::memcmp(expected, other.c_str(), strlen(expected)));
2484 bufferlist malformed;
2485 malformed.append("QUJDRA");
2486 EXPECT_THROW(other.decode_base64(malformed), buffer::malformed_input);
2489 TEST(BufferList, hexdump) {
2491 std::ostringstream stream;
2492 bl.append("013245678901234\0006789012345678901234", 32);
2494 EXPECT_EQ("00000000 30 31 33 32 34 35 36 37 38 39 30 31 32 33 34 00 |013245678901234.|\n"
2495 "00000010 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 |6789012345678901|\n"
2500 TEST(BufferList, read_file) {
2504 EXPECT_EQ(-ENOENT, bl.read_file("UNLIKELY", &error));
2505 snprintf(cmd, sizeof(cmd), "echo ABC > %s ; chmod 0 %s", FILENAME, FILENAME);
2506 EXPECT_EQ(0, ::system(cmd));
2507 if (getuid() != 0) {
2508 EXPECT_EQ(-EACCES, bl.read_file(FILENAME, &error));
2510 snprintf(cmd, sizeof(cmd), "chmod +r %s", FILENAME);
2511 EXPECT_EQ(0, ::system(cmd));
2512 EXPECT_EQ(0, bl.read_file(FILENAME, &error));
2514 EXPECT_EQ((unsigned)4, bl.length());
2515 std::string actual(bl.c_str(), bl.length());
2516 EXPECT_EQ("ABC\n", actual);
2519 TEST(BufferList, read_fd) {
2522 snprintf(cmd, sizeof(cmd), "echo ABC > %s", FILENAME);
2523 EXPECT_EQ(0, ::system(cmd));
2526 EXPECT_EQ(-EBADF, bl.read_fd(fd, len));
2527 fd = ::open(FILENAME, O_RDONLY);
2528 EXPECT_EQ(len, (unsigned)bl.read_fd(fd, len));
2529 //EXPECT_EQ(CEPH_BUFFER_APPEND_SIZE - len, bl.front().unused_tail_length());
2530 EXPECT_EQ(len, bl.length());
2535 TEST(BufferList, write_file) {
2539 EXPECT_EQ(-ENOENT, bl.write_file("un/like/ly", mode));
2541 EXPECT_EQ(0, bl.write_file(FILENAME, mode));
2543 memset(&st, 0, sizeof(st));
2544 ::stat(FILENAME, &st);
2545 EXPECT_EQ((unsigned)(mode | S_IFREG), st.st_mode);
2549 TEST(BufferList, write_fd) {
2551 int fd = ::open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
2553 for (unsigned i = 0; i < IOV_MAX * 2; i++) {
2554 bufferptr ptr("A", 1);
2557 EXPECT_EQ(0, bl.write_fd(fd));
2560 memset(&st, 0, sizeof(st));
2561 ::stat(FILENAME, &st);
2562 EXPECT_EQ(IOV_MAX * 2, st.st_size);
2566 TEST(BufferList, write_fd_offset) {
2568 int fd = ::open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
2570 for (unsigned i = 0; i < IOV_MAX * 2; i++) {
2571 bufferptr ptr("A", 1);
2574 uint64_t offset = 200;
2575 EXPECT_EQ(0, bl.write_fd(fd, offset));
2578 memset(&st, 0, sizeof(st));
2579 ::stat(FILENAME, &st);
2580 EXPECT_EQ(IOV_MAX * 2 + offset, (unsigned)st.st_size);
2584 TEST(BufferList, crc32c) {
2588 crc = bl.crc32c(crc);
2589 EXPECT_EQ((unsigned)0xB3109EBF, crc);
2590 crc = bl.crc32c(crc);
2591 EXPECT_EQ((unsigned)0x5FA5C0CC, crc);
2594 TEST(BufferList, crc32c_append) {
2598 for (int j = 0; j < 200; ++j) {
2600 for (int i = 0; i < 200; ++i) {
2605 bl.crc32c(rand()); // mess with the cached bufferptr crc values
2608 ASSERT_EQ(bl1.crc32c(0), bl2.crc32c(0));
2611 TEST(BufferList, crc32c_zeros) {
2612 char buffer[4*1024];
2613 for (size_t i=0; i < sizeof(buffer); i++)
2621 for (size_t j=0; j < 1000; j++)
2623 bufferptr a(buffer, sizeof(buffer));
2626 uint32_t crca = bla.crc32c(111);
2629 uint32_t crcb = ceph_crc32c(111, (unsigned char*)blb.c_str(), blb.length());
2631 EXPECT_EQ(crca, crcb);
2635 TEST(BufferList, crc32c_append_perf) {
2636 int len = 256 * 1024 * 1024;
2641 std::cout << "populating large buffers (a, b=c=d)" << std::endl;
2642 char *pa = a.c_str();
2643 char *pb = b.c_str();
2644 char *pc = c.c_str();
2645 char *pd = c.c_str();
2646 for (int i=0; i<len; i++) {
2647 pa[i] = (i & 0xff) ^ 73;
2648 pb[i] = (i & 0xff) ^ 123;
2649 pc[i] = (i & 0xff) ^ 123;
2650 pd[i] = (i & 0xff) ^ 123;
2653 // track usage of cached crcs
2654 buffer::track_cached_crc(true);
2656 int base_cached = buffer::get_cached_crc();
2657 int base_cached_adjusted = buffer::get_cached_crc_adjusted();
2664 utime_t start = ceph_clock_now();
2665 uint32_t r = bla.crc32c(0);
2666 utime_t end = ceph_clock_now();
2667 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2668 std::cout << "a.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2669 ASSERT_EQ(r, 1138817026u);
2671 assert(buffer::get_cached_crc() == 0 + base_cached);
2673 utime_t start = ceph_clock_now();
2674 uint32_t r = bla.crc32c(0);
2675 utime_t end = ceph_clock_now();
2676 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2677 std::cout << "a.crc32c(0) (again) = " << r << " at " << rate << " MB/sec" << std::endl;
2678 ASSERT_EQ(r, 1138817026u);
2680 assert(buffer::get_cached_crc() == 1 + base_cached);
2683 utime_t start = ceph_clock_now();
2684 uint32_t r = bla.crc32c(5);
2685 utime_t end = ceph_clock_now();
2686 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2687 std::cout << "a.crc32c(5) = " << r << " at " << rate << " MB/sec" << std::endl;
2688 ASSERT_EQ(r, 3239494520u);
2690 assert(buffer::get_cached_crc() == 1 + base_cached);
2691 assert(buffer::get_cached_crc_adjusted() == 1 + base_cached_adjusted);
2693 utime_t start = ceph_clock_now();
2694 uint32_t r = bla.crc32c(5);
2695 utime_t end = ceph_clock_now();
2696 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2697 std::cout << "a.crc32c(5) (again) = " << r << " at " << rate << " MB/sec" << std::endl;
2698 ASSERT_EQ(r, 3239494520u);
2700 assert(buffer::get_cached_crc() == 1 + base_cached);
2701 assert(buffer::get_cached_crc_adjusted() == 2 + base_cached_adjusted);
2703 utime_t start = ceph_clock_now();
2704 uint32_t r = blb.crc32c(0);
2705 utime_t end = ceph_clock_now();
2706 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2707 std::cout << "b.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2708 ASSERT_EQ(r, 2481791210u);
2710 assert(buffer::get_cached_crc() == 1 + base_cached);
2712 utime_t start = ceph_clock_now();
2713 uint32_t r = blb.crc32c(0);
2714 utime_t end = ceph_clock_now();
2715 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2716 std::cout << "b.crc32c(0) (again)= " << r << " at " << rate << " MB/sec" << std::endl;
2717 ASSERT_EQ(r, 2481791210u);
2719 assert(buffer::get_cached_crc() == 2 + base_cached);
2725 utime_t start = ceph_clock_now();
2726 uint32_t r = ab.crc32c(0);
2727 utime_t end = ceph_clock_now();
2728 float rate = (float)ab.length() / (float)(1024*1024) / (float)(end - start);
2729 std::cout << "ab.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2730 ASSERT_EQ(r, 2988268779u);
2732 assert(buffer::get_cached_crc() == 3 + base_cached);
2733 assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted);
2738 utime_t start = ceph_clock_now();
2739 uint32_t r = ac.crc32c(0);
2740 utime_t end = ceph_clock_now();
2741 float rate = (float)ac.length() / (float)(1024*1024) / (float)(end - start);
2742 std::cout << "ac.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2743 ASSERT_EQ(r, 2988268779u);
2745 assert(buffer::get_cached_crc() == 4 + base_cached);
2746 assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted);
2752 utime_t start = ceph_clock_now();
2753 uint32_t r = ba.crc32c(0);
2754 utime_t end = ceph_clock_now();
2755 float rate = (float)ba.length() / (float)(1024*1024) / (float)(end - start);
2756 std::cout << "ba.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2757 ASSERT_EQ(r, 169240695u);
2759 assert(buffer::get_cached_crc() == 5 + base_cached);
2760 assert(buffer::get_cached_crc_adjusted() == 4 + base_cached_adjusted);
2762 utime_t start = ceph_clock_now();
2763 uint32_t r = ba.crc32c(5);
2764 utime_t end = ceph_clock_now();
2765 float rate = (float)ba.length() / (float)(1024*1024) / (float)(end - start);
2766 std::cout << "ba.crc32c(5) = " << r << " at " << rate << " MB/sec" << std::endl;
2767 ASSERT_EQ(r, 1265464778u);
2769 assert(buffer::get_cached_crc() == 5 + base_cached);
2770 assert(buffer::get_cached_crc_adjusted() == 6 + base_cached_adjusted);
2772 cout << "crc cache hits (same start) = " << buffer::get_cached_crc() << std::endl;
2773 cout << "crc cache hits (adjusted) = " << buffer::get_cached_crc_adjusted() << std::endl;
2776 TEST(BufferList, compare) {
2784 // bool operator>(bufferlist& l, bufferlist& r)
2786 ASSERT_FALSE(a > ab);
2787 ASSERT_TRUE(ab > a);
2788 ASSERT_TRUE(ac > ab);
2789 ASSERT_FALSE(ab > ac);
2790 ASSERT_FALSE(ab > ab);
2792 // bool operator>=(bufferlist& l, bufferlist& r)
2794 ASSERT_FALSE(a >= ab);
2795 ASSERT_TRUE(ab >= a);
2796 ASSERT_TRUE(ac >= ab);
2797 ASSERT_FALSE(ab >= ac);
2798 ASSERT_TRUE(ab >= ab);
2800 // bool operator<(bufferlist& l, bufferlist& r)
2802 ASSERT_TRUE(a < ab);
2803 ASSERT_FALSE(ab < a);
2804 ASSERT_FALSE(ac < ab);
2805 ASSERT_TRUE(ab < ac);
2806 ASSERT_FALSE(ab < ab);
2808 // bool operator<=(bufferlist& l, bufferlist& r)
2810 ASSERT_TRUE(a <= ab);
2811 ASSERT_FALSE(ab <= a);
2812 ASSERT_FALSE(ac <= ab);
2813 ASSERT_TRUE(ab <= ac);
2814 ASSERT_TRUE(ab <= ab);
2816 // bool operator==(bufferlist &l, bufferlist &r)
2818 ASSERT_FALSE(a == ab);
2819 ASSERT_FALSE(ac == ab);
2820 ASSERT_TRUE(ab == ab);
2823 TEST(BufferList, ostream) {
2824 std::ostringstream stream;
2830 for (unsigned i = 0; i < 2; i++) {
2831 bufferptr ptr(s[i], strlen(s[i]));
2835 std::cerr << stream.str() << std::endl;
2836 EXPECT_GT(stream.str().size(), stream.str().find("list(len=6,"));
2837 EXPECT_GT(stream.str().size(), stream.str().find("len 3 nref 1),\n"));
2838 EXPECT_GT(stream.str().size(), stream.str().find("len 3 nref 1)\n"));
2841 TEST(BufferList, zero) {
2848 EXPECT_EQ('A', bl[0]);
2850 EXPECT_EQ('\0', bl[0]);
2853 // void zero(unsigned o, unsigned l)
2863 bufferptr ptr(s[0], strlen(s[0]));
2865 bl.zero((unsigned)0, (unsigned)1);
2866 EXPECT_EQ(0, ::memcmp("\0BC", bl.c_str(), 3));
2870 for (unsigned i = 0; i < 4; i++) {
2871 bufferptr ptr(s[i], strlen(s[i]));
2875 PrCtl unset_dumpable;
2876 EXPECT_DEATH(bl.zero((unsigned)0, (unsigned)2000), "");
2878 bl.zero((unsigned)2, (unsigned)5);
2879 EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl.c_str(), 9));
2883 for (unsigned i = 0; i < 4; i++) {
2884 bufferptr ptr(s[i], strlen(s[i]));
2887 bl.zero((unsigned)3, (unsigned)3);
2888 EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl.c_str(), 9));
2894 memset(ptr1.c_str(), 'a', 4);
2895 memset(ptr2.c_str(), 'b', 4);
2898 bl.zero((unsigned)2, (unsigned)4);
2899 EXPECT_EQ(0, ::memcmp("aa\0\0\0\0bb", bl.c_str(), 8));
2903 TEST(BufferList, EmptyAppend) {
2907 ASSERT_EQ(bl.begin().end(), 1);
2910 TEST(BufferList, TestPtrAppend) {
2912 char correct[MAX_TEST];
2914 int length = random() % 5 > 0 ? random() % 1000 : 0;
2915 while (curpos + length < MAX_TEST) {
2920 char *current = correct + curpos;
2921 for (int i = 0; i < length; ++i) {
2922 char next = random() % 255;
2923 correct[curpos++] = next;
2925 bufferptr ptr(current, length);
2928 length = random() % 5 > 0 ? random() % 1000 : 0;
2930 ASSERT_EQ(memcmp(bl.c_str(), correct, curpos), 0);
2933 TEST(BufferList, TestDirectAppend) {
2935 char correct[MAX_TEST];
2937 int length = random() % 5 > 0 ? random() % 1000 : 0;
2938 while (curpos + length < MAX_TEST) {
2939 char *current = correct + curpos;
2940 for (int i = 0; i < length; ++i) {
2941 char next = random() % 255;
2942 correct[curpos++] = next;
2944 bl.append(current, length);
2945 length = random() % 5 > 0 ? random() % 1000 : 0;
2947 ASSERT_EQ(memcmp(bl.c_str(), correct, curpos), 0);
2950 TEST(BufferList, TestCloneNonShareable) {
2952 std::string str = "sharetest";
2953 bl.append(str.c_str(), 9);
2954 bufferlist bl_share;
2956 bufferlist bl_noshare;
2957 buffer::ptr unraw = buffer::create_unshareable(10);
2958 unraw.copy_in(0, 9, str.c_str());
2959 bl_noshare.append(unraw);
2960 bufferlist bl_copied_share = bl_share;
2961 bufferlist bl_copied_noshare = bl_noshare;
2963 // assert shared bufferlist has same buffers
2964 bufferlist::iterator iter_bl = bl.begin();
2965 bufferlist::iterator iter_bl_share = bl_share.begin();
2966 // ok, this considers ptr::off, but it's still a true assertion (and below)
2967 ASSERT_TRUE(iter_bl.get_current_ptr().c_str() ==
2968 iter_bl_share.get_current_ptr().c_str());
2970 // assert copy of shareable bufferlist has same buffers
2971 iter_bl = bl.begin();
2972 bufferlist::iterator iter_bl_copied_share = bl_copied_share.begin();
2973 ASSERT_TRUE(iter_bl.get_current_ptr().c_str() ==
2974 iter_bl_copied_share.get_current_ptr().c_str());
2976 // assert copy of non-shareable bufferlist has different buffers
2977 bufferlist::iterator iter_bl_copied_noshare = bl_copied_noshare.begin();
2978 ASSERT_FALSE(iter_bl.get_current_ptr().c_str() ==
2979 iter_bl_copied_noshare.get_current_ptr().c_str());
2981 // assert that claim with CLAIM_ALLOW_NONSHAREABLE overrides safe-sharing
2982 bufferlist bl_claim_noshare_override;
2983 void* addr = bl_noshare.begin().get_current_ptr().c_str();
2984 bl_claim_noshare_override.claim(bl_noshare,
2985 buffer::list::CLAIM_ALLOW_NONSHAREABLE);
2986 bufferlist::iterator iter_bl_noshare_override =
2987 bl_claim_noshare_override.begin();
2988 ASSERT_TRUE(addr /* the original first segment of bl_noshare() */ ==
2989 iter_bl_noshare_override.get_current_ptr().c_str());
2992 TEST(BufferList, TestCopyAll) {
2993 const static size_t BIG_SZ = 10737414;
2994 ceph::shared_ptr <unsigned char> big(
2995 (unsigned char*)malloc(BIG_SZ), free);
2996 unsigned char c = 0;
2997 for (size_t i = 0; i < BIG_SZ; ++i) {
3001 bl.append((const char*)big.get(), BIG_SZ);
3002 bufferlist::iterator i = bl.begin();
3005 ASSERT_EQ(bl2.length(), BIG_SZ);
3006 ceph::shared_ptr <unsigned char> big2(
3007 (unsigned char*)malloc(BIG_SZ), free);
3008 bl2.copy(0, BIG_SZ, (char*)big2.get());
3009 ASSERT_EQ(memcmp(big.get(), big2.get(), BIG_SZ), 0);
3012 TEST(BufferList, InvalidateCrc) {
3013 const static size_t buffer_size = 262144;
3014 ceph::shared_ptr <unsigned char> big(
3015 (unsigned char*)malloc(buffer_size), free);
3016 unsigned char c = 0;
3017 char* ptr = (char*) big.get();
3019 for (size_t i = 0; i < buffer_size; ++i) {
3024 // test for crashes (shouldn't crash)
3025 bl.invalidate_crc();
3027 // put data into bufferlist
3028 bl.append((const char*)big.get(), buffer_size);
3031 __u32 crc = bl.crc32c(0);
3033 // modify data in bl without its knowledge
3034 inptr = (char*) bl.c_str();
3036 for (size_t i = 0; i < buffer_size; ++i) {
3040 // make sure data in bl are now different than in big
3041 EXPECT_NE(memcmp((void*) ptr, (void*) inptr, buffer_size), 0);
3043 // crc should remain the same
3044 __u32 new_crc = bl.crc32c(0);
3045 EXPECT_EQ(crc, new_crc);
3047 // force crc invalidate, check if it is updated
3048 bl.invalidate_crc();
3049 EXPECT_NE(crc, bl.crc32c(0));
3052 TEST(BufferList, TestIsProvidedBuffer) {
3055 bl.push_back(buffer::create_static(100, buff));
3056 ASSERT_TRUE(bl.is_provided_buffer(buff));
3057 bl.append_zero(100);
3058 ASSERT_FALSE(bl.is_provided_buffer(buff));
3061 TEST(BufferHash, all) {
3066 EXPECT_EQ((unsigned)0, hash.digest());
3068 EXPECT_EQ((unsigned)0xB3109EBF, hash.digest());
3070 EXPECT_EQ((unsigned)0x5FA5C0CC, hash.digest());
3076 EXPECT_EQ((unsigned)0, hash.digest());
3077 bufferhash& returned_hash = hash << bl;
3078 EXPECT_EQ(&returned_hash, &hash);
3079 EXPECT_EQ((unsigned)0xB3109EBF, hash.digest());
3085 * compile-command: "cd .. ; make unittest_bufferlist &&
3086 * ulimit -s unlimited ; CEPH_BUFFER_TRACK=true valgrind \
3087 * --max-stackframe=20000000 --tool=memcheck \
3088 * ./unittest_bufferlist # --gtest_filter=BufferList.constructors"