From: Loic Dachary <loic@dachary.org>
To: Sage Weil <sage@inktank.com>
Cc: ceph-devel@vger.kernel.org
Subject: Re: [PATCH] unit tests for src/common/buffer.{cc,h}
Date: Mon, 18 Feb 2013 08:17:52 +0100 [thread overview]
Message-ID: <5121D5A0.5000807@dachary.org> (raw)
In-Reply-To: <alpine.DEB.2.00.1302172147510.25660@cobra.newdream.net>
[-- Attachment #1: Type: text/plain, Size: 62182 bytes --]
Hi Sage,
On 02/18/2013 06:48 AM, Sage Weil wrote:
> Hi Loic,
>
> I merged this in, which two small changes:
Thanks !
> - the malloc ULLONG_MAX tests were succeeding and eating RAM on my box;
> commented them out.
You have a lot of RAM ( kidding ). I'll investigate and find a safe way to fail memory allocation.
> - the BIG_SZ buffer on teh stack was segfaulting; put it on the heap.
That was not a test I wrote and I worked around the problem with
ulimit -s unlimited ; make unittest_bufferlist
but the heap is a better choice. I was not sure if allocating in the stack was deliberate or not.
>
> Otherwise, looks great! I'm very pleased to have test coverage on this
> code. :)
It was an interesting experience :-) I'll write a small blog post about the buffers before I forget the details.
Cheers
> sage
>
>
> On Sun, 17 Feb 2013, Loic Dachary wrote:
>
>> Implement unit tests covering most lines of code ( > 92% ) and all
>> methods as show by the output of make check-coverage :
>> http://dachary.org/wp-uploads/2013/03/ceph-lcov/ .
>>
>> The following static constructors are implemented by opaque classes
>> defined in buffer.cc ( buffer::raw_char, buffer::raw_posix_aligned
>> etc. ). Testing the implementation of these classes is done by
>> variations of the calls to the static constructors.
>>
>> copy(const char *c, unsigned len);
>> create(unsigned len);
>> claim_char(unsigned len, char *buf);
>> create_malloc(unsigned len);
>> claim_malloc(unsigned len, char *buf);
>> create_static(unsigned len, char *buf);
>> create_page_aligned(unsigned len);
>>
>> The raw_mmap_pages class cannot be tested because it is commented out in
>> raw_posix_aligned. The raw_hack_aligned class is only tested under Cygwin.
>> The raw_posix_aligned class is not tested under Cygwin.
>>
>> The unittest_bufferlist.sh script calls unittest_bufferlist with the
>> CEPH_BUFFER_TRACK=true environment variable to enable the code
>> tracking the memory usage. It cannot be done within the bufferlist.cc
>> file itself because it relies on the initialization of a global
>> variable ( buffer_track_alloc ).
>>
>> When raw_posix_aligned is called on DARWIN, the data is not aligned
>> on CEPH_PAGE_SIZE because it calls valloc(size) which is the equivalent of
>> memalign(sysconf(_SC_PAGESIZE),size) and not memalign(CEPH_PAGE_SIZE,size).
>> For this reason the alignment test is de-activated on DARWIN.
>>
>> The tests are grouped in
>>
>> TEST(BufferPtr, ... ) for buffer::ptr
>> TEST(BufferListIterator, ...) for buffer::list::iterator
>> TEST(BufferList, ...) for buffer::list
>> TEST(BufferHash, ...) for buffer::hash
>>
>> and each method ( and all variations of the prototype ) are
>> included into a single TEST() function.
>>
>> Although most aspects of the methods are tested, including exceptions
>> and border cases, inconsistencies are not highlighted . For
>> instance
>>
>> buffer::list::iterator i;
>> i.advance(1);
>>
>> would dereference a buffer::raw NULL pointer although
>>
>> buffer::ptr p;
>> p.wasted()
>>
>> asserts instead of dereferencing the buffer::raw NULL pointer. It
>> would be better to always assert in case a NULL pointer is about to be
>> used. But this is a minor inconsistency that is probably not worth a
>> test.
>>
>> The following buffer::list methods
>>
>> ssize_t read_fd(int fd, size_t len);
>> int write_fd(int fd) const;
>>
>> are not fully tested because the border cases cannot be reliably
>> reproduced. Going thru a pointer indirection when calling the ::writev
>> or safe_read functions would allow the test to create mockups to synthetize
>> the conditions for border cases.
>>
>> tracker.ceph.com/issues/4066 refs #4066
>>
>> Signed-off-by: Loic Dachary <loic@dachary.org>
>> ---
>> src/Makefile.am | 5 +-
>> src/test/bufferlist.cc | 1801 +++++++++++++++++++++++++++++++++++++++++---
>> src/unittest_bufferlist.sh | 19 +
>> 3 files changed, 1731 insertions(+), 94 deletions(-)
>> create mode 100755 src/unittest_bufferlist.sh
>>
>> diff --git a/src/Makefile.am b/src/Makefile.am
>> index 556de51..1725588 100644
>> --- a/src/Makefile.am
>> +++ b/src/Makefile.am
>> @@ -19,7 +19,8 @@ EXTRA_DIST = \
>> libs3/libs3.spec \
>> libs3/mswin \
>> libs3/src \
>> - libs3/test
>> + libs3/test \
>> + unittest_bufferlist.sh
>>
>> CLEANFILES =
>> bin_PROGRAMS =
>> @@ -38,7 +39,7 @@ check_PROGRAMS =
>> # tests to actually run on "make check"; if you need extra, non-test,
>> # executables built, you need to replace this with manual assignments
>> # target by target
>> -TESTS = $(check_PROGRAMS)
>> +TESTS = $(check_PROGRAMS) unittest_bufferlist.sh
>>
>> check-local:
>> $(srcdir)/test/encoding/check-generated.sh
>> diff --git a/src/test/bufferlist.cc b/src/test/bufferlist.cc
>> index 7abced1..6f8ba19 100644
>> --- a/src/test/bufferlist.cc
>> +++ b/src/test/bufferlist.cc
>> @@ -1,77 +1,1650 @@
>> +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
>> +// vim: ts=8 sw=2 smarttab
>> +/*
>> + * Ceph - scalable distributed file system
>> + *
>> + * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
>> + *
>> + * Author: Loic Dachary <loic@dachary.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU Library Public License as published by
>> + * the Free Software Foundation; either version 2, or (at your option)
>> + * any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU Library Public License for more details.
>> + *
>> + */
>> +
>> #include <tr1/memory>
>> +#include <limits.h>
>> +#include <errno.h>
>> +#include <sys/uio.h>
>>
>> #include "include/buffer.h"
>> #include "include/encoding.h"
>> +#include "common/environment.h"
>>
>> #include "gtest/gtest.h"
>> #include "stdlib.h"
>> -
>> +#include "fcntl.h"
>> +#include "sys/stat.h"
>>
>> #define MAX_TEST 1000000
>>
>> -TEST(BufferPtr, cmp) {
>> - bufferptr empty;
>> - bufferptr a("A", 1);
>> - bufferptr ab("AB", 2);
>> - bufferptr af("AF", 2);
>> - bufferptr acc("ACC", 3);
>> - EXPECT_GE(-1, empty.cmp(a));
>> - EXPECT_LE(1, a.cmp(empty));
>> - EXPECT_GE(-1, a.cmp(ab));
>> - EXPECT_LE(1, ab.cmp(a));
>> - EXPECT_EQ(0, ab.cmp(ab));
>> - EXPECT_GE(-1, ab.cmp(af));
>> - EXPECT_LE(1, af.cmp(ab));
>> - EXPECT_GE(-1, acc.cmp(af));
>> - EXPECT_LE(1, af.cmp(acc));
>> +TEST(Buffer, constructors) {
>> + bool ceph_buffer_track = get_env_bool("CEPH_BUFFER_TRACK");
>> + unsigned len = 17;
>> + //
>> + // buffer::create
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + bufferptr ptr(buffer::create(len));
>> + EXPECT_EQ(len, ptr.length());
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
>> + }
>> + //
>> + // buffer::claim_char
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + char* str = new char[len];
>> + ::memset(str, 'X', len);
>> + bufferptr ptr(buffer::claim_char(len, str));
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_EQ(str, ptr.c_str());
>> + bufferptr clone = ptr.clone();
>> + EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
>> + }
>> + //
>> + // buffer::create_static
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + char* str = new char[len];
>> + bufferptr ptr(buffer::create_static(len, str));
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_EQ(str, ptr.c_str());
>> + delete [] str;
>> + }
>> + //
>> + // buffer::create_malloc
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + bufferptr ptr(buffer::create_malloc(len));
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_THROW(buffer::create_malloc((unsigned)ULLONG_MAX), buffer::bad_alloc);
>> + }
>> + //
>> + // buffer::claim_malloc
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + char* str = (char*)malloc(len);
>> + ::memset(str, 'X', len);
>> + bufferptr ptr(buffer::claim_malloc(len, str));
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_EQ(str, ptr.c_str());
>> + bufferptr clone = ptr.clone();
>> + EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
>> + }
>> + //
>> + // buffer::copy
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + const std::string expected(len, 'X');
>> + bufferptr ptr(buffer::copy(expected.c_str(), expected.size()));
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
>> + EXPECT_NE(expected.c_str(), ptr.c_str());
>> + EXPECT_EQ(0, ::memcmp(expected.c_str(), ptr.c_str(), len));
>> + }
>> + //
>> + // buffer::create_page_aligned
>> + //
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> + {
>> + bufferptr ptr(buffer::create_page_aligned(len));
>> + ::memset(ptr.c_str(), 'X', len);
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(len, (unsigned)buffer::get_total_alloc());
>> + EXPECT_THROW(buffer::create_page_aligned((unsigned)ULLONG_MAX), buffer::bad_alloc);
>> +#ifndef DARWIN
>> + ASSERT_TRUE(ptr.is_page_aligned());
>> +#endif // DARWIN
>> + bufferptr clone = ptr.clone();
>> + EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
>> + }
>> + if (ceph_buffer_track)
>> + EXPECT_EQ(0, buffer::get_total_alloc());
>> +}
>> +
>> +TEST(BufferRaw, ostream) {
>> + bufferptr ptr(1);
>> + std::ostringstream stream;
>> + stream << *ptr.get_raw();
>> + EXPECT_GT(stream.str().size(), stream.str().find("buffer::raw("));
>> + EXPECT_GT(stream.str().size(), stream.str().find("len 1 nref 1)"));
>> +}
>> +
>> +//
>> +// +-----------+ +-----+
>> +// | | | |
>> +// | offset +----------------+ |
>> +// | | | |
>> +// | length +---- | |
>> +// | | \------- | |
>> +// +-----------+ \---+ |
>> +// | ptr | +-----+
>> +// +-----------+ | raw |
>> +// +-----+
>> +//
>> +TEST(BufferPtr, constructors) {
>> + unsigned len = 17;
>> + //
>> + // ptr::ptr()
>> + //
>> + {
>> + buffer::ptr ptr;
>> + EXPECT_FALSE(ptr.have_raw());
>> + EXPECT_EQ((unsigned)0, ptr.offset());
>> + EXPECT_EQ((unsigned)0, ptr.length());
>> + }
>> + //
>> + // ptr::ptr(raw *r)
>> + //
>> + {
>> + bufferptr ptr(buffer::create(len));
>> + EXPECT_TRUE(ptr.have_raw());
>> + EXPECT_EQ((unsigned)0, ptr.offset());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_EQ(ptr.raw_length(), ptr.length());
>> + EXPECT_EQ(1, ptr.raw_nref());
>> + }
>> + //
>> + // ptr::ptr(unsigned l)
>> + //
>> + {
>> + bufferptr ptr(len);
>> + EXPECT_TRUE(ptr.have_raw());
>> + EXPECT_EQ((unsigned)0, ptr.offset());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_EQ(1, ptr.raw_nref());
>> + }
>> + //
>> + // ptr(const char *d, unsigned l)
>> + //
>> + {
>> + const std::string str(len, 'X');
>> + bufferptr ptr(str.c_str(), len);
>> + EXPECT_TRUE(ptr.have_raw());
>> + EXPECT_EQ((unsigned)0, ptr.offset());
>> + EXPECT_EQ(len, ptr.length());
>> + EXPECT_EQ(1, ptr.raw_nref());
>> + EXPECT_EQ(0, ::memcmp(str.c_str(), ptr.c_str(), len));
>> + }
>> + //
>> + // ptr(const ptr& p)
>> + //
>> + {
>> + const std::string str(len, 'X');
>> + bufferptr original(str.c_str(), len);
>> + bufferptr ptr(original);
>> + EXPECT_TRUE(ptr.have_raw());
>> + EXPECT_EQ(original.get_raw(), ptr.get_raw());
>> + EXPECT_EQ(2, ptr.raw_nref());
>> + EXPECT_EQ(0, ::memcmp(original.c_str(), ptr.c_str(), len));
>> + }
>> + //
>> + // ptr(const ptr& p, unsigned o, unsigned l)
>> + //
>> + {
>> + const std::string str(len, 'X');
>> + bufferptr original(str.c_str(), len);
>> + bufferptr ptr(original, 0, 0);
>> + EXPECT_TRUE(ptr.have_raw());
>> + EXPECT_EQ(original.get_raw(), ptr.get_raw());
>> + EXPECT_EQ(2, ptr.raw_nref());
>> + EXPECT_EQ(0, ::memcmp(original.c_str(), ptr.c_str(), len));
>> + EXPECT_THROW(bufferptr(original, 0, original.length() + 1), FailedAssertion);
>> + EXPECT_THROW(bufferptr(bufferptr(), 0, 0), FailedAssertion);
>> + }
>> +}
>> +
>> +TEST(BufferPtr, assignment) {
>> + unsigned len = 17;
>> + //
>> + // override a bufferptr set with the same raw
>> + //
>> + {
>> + bufferptr original(len);
>> + bufferptr same_raw(original.get_raw());
>> + unsigned offset = 5;
>> + unsigned length = len - offset;
>> + original.set_offset(offset);
>> + original.set_length(length);
>> + same_raw = original;
>> + ASSERT_EQ(2, original.raw_nref());
>> + ASSERT_EQ(same_raw.get_raw(), original.get_raw());
>> + ASSERT_EQ(same_raw.offset(), original.offset());
>> + ASSERT_EQ(same_raw.length(), original.length());
>> + }
>> +
>> + //
>> + // self assignment is a noop
>> + //
>> + {
>> + bufferptr original(len);
>> + original = original;
>> + ASSERT_EQ(1, original.raw_nref());
>> + ASSERT_EQ((unsigned)0, original.offset());
>> + ASSERT_EQ(len, original.length());
>> + }
>> +
>> + //
>> + // a copy points to the same raw
>> + //
>> + {
>> + bufferptr original(len);
>> + unsigned offset = 5;
>> + unsigned length = len - offset;
>> + original.set_offset(offset);
>> + original.set_length(length);
>> + bufferptr ptr;
>> + ptr = original;
>> + ASSERT_EQ(2, original.raw_nref());
>> + ASSERT_EQ(ptr.get_raw(), original.get_raw());
>> + ASSERT_EQ(original.offset(), ptr.offset());
>> + ASSERT_EQ(original.length(), ptr.length());
>> + }
>> +}
>> +
>> +TEST(BufferPtr, clone) {
>> + unsigned len = 17;
>> + bufferptr ptr(len);
>> + ::memset(ptr.c_str(), 'X', len);
>> + bufferptr clone = ptr.clone();
>> + EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
>> +}
>> +
>> +TEST(BufferPtr, swap) {
>> + unsigned len = 17;
>> +
>> + bufferptr ptr1(len);
>> + ::memset(ptr1.c_str(), 'X', len);
>> + unsigned ptr1_offset = 4;
>> + ptr1.set_offset(ptr1_offset);
>> + unsigned ptr1_length = 3;
>> + ptr1.set_length(ptr1_length);
>> +
>> + bufferptr ptr2(len);
>> + ::memset(ptr2.c_str(), 'Y', len);
>> + unsigned ptr2_offset = 5;
>> + ptr2.set_offset(ptr2_offset);
>> + unsigned ptr2_length = 7;
>> + ptr2.set_length(ptr2_length);
>> +
>> + ptr1.swap(ptr2);
>> +
>> + EXPECT_EQ(ptr2_length, ptr1.length());
>> + EXPECT_EQ(ptr2_offset, ptr1.offset());
>> + EXPECT_EQ('Y', ptr1[0]);
>> +
>> + EXPECT_EQ(ptr1_length, ptr2.length());
>> + EXPECT_EQ(ptr1_offset, ptr2.offset());
>> + EXPECT_EQ('X', ptr2[0]);
>> +}
>> +
>> +TEST(BufferPtr, release) {
>> + unsigned len = 17;
>> +
>> + bufferptr ptr1(len);
>> + {
>> + bufferptr ptr2(ptr1);
>> + EXPECT_EQ(2, ptr1.raw_nref());
>> + }
>> + EXPECT_EQ(1, ptr1.raw_nref());
>> +}
>> +
>> +TEST(BufferPtr, have_raw) {
>> + {
>> + bufferptr ptr;
>> + EXPECT_FALSE(ptr.have_raw());
>> + }
>> + {
>> + bufferptr ptr(1);
>> + EXPECT_TRUE(ptr.have_raw());
>> + }
>> +}
>> +
>> +TEST(BufferPtr, at_buffer_head) {
>> + bufferptr ptr(2);
>> + EXPECT_TRUE(ptr.at_buffer_head());
>> + ptr.set_offset(1);
>> + EXPECT_FALSE(ptr.at_buffer_head());
>> +}
>> +
>> +TEST(BufferPtr, at_buffer_tail) {
>> + bufferptr ptr(2);
>> + EXPECT_TRUE(ptr.at_buffer_tail());
>> + ptr.set_length(1);
>> + EXPECT_FALSE(ptr.at_buffer_tail());
>> +}
>> +
>> +TEST(BufferPtr, is_n_page_sized) {
>> + {
>> + bufferptr ptr(CEPH_PAGE_SIZE);
>> + EXPECT_TRUE(ptr.is_n_page_sized());
>> + }
>> + {
>> + bufferptr ptr(1);
>> + EXPECT_FALSE(ptr.is_n_page_sized());
>> + }
>> +}
>> +
>> +TEST(BufferPtr, accessors) {
>> + unsigned len = 17;
>> + bufferptr ptr(len);
>> + ptr.c_str()[0] = 'X';
>> + ptr[1] = 'Y';
>> + const bufferptr const_ptr(ptr);
>> +
>> + EXPECT_NE((void*)NULL, (void*)ptr.get_raw());
>> + EXPECT_EQ('X', ptr.c_str()[0]);
>> + {
>> + bufferptr ptr;
>> + EXPECT_THROW(ptr.c_str(), FailedAssertion);
>> + EXPECT_THROW(ptr[0], FailedAssertion);
>> + }
>> + EXPECT_EQ('X', const_ptr.c_str()[0]);
>> + {
>> + const bufferptr const_ptr;
>> + EXPECT_THROW(const_ptr.c_str(), FailedAssertion);
>> + EXPECT_THROW(const_ptr[0], FailedAssertion);
>> + }
>> + EXPECT_EQ(len, const_ptr.length());
>> + EXPECT_EQ((unsigned)0, const_ptr.offset());
>> + EXPECT_EQ((unsigned)0, const_ptr.start());
>> + EXPECT_EQ(len, const_ptr.end());
>> + EXPECT_EQ(len, const_ptr.end());
>> + {
>> + bufferptr ptr(len);
>> + unsigned unused = 1;
>> + ptr.set_length(ptr.length() - unused);
>> + EXPECT_EQ(unused, ptr.unused_tail_length());
>> + }
>> + {
>> + bufferptr ptr;
>> + EXPECT_EQ((unsigned)0, ptr.unused_tail_length());
>> + }
>> + EXPECT_THROW(ptr[len], FailedAssertion);
>> + EXPECT_THROW(const_ptr[len], FailedAssertion);
>> + {
>> + const bufferptr const_ptr;
>> + EXPECT_THROW(const_ptr.raw_c_str(), FailedAssertion);
>> + EXPECT_THROW(const_ptr.raw_length(), FailedAssertion);
>> + EXPECT_THROW(const_ptr.raw_nref(), FailedAssertion);
>> + }
>> + EXPECT_NE((const char *)NULL, const_ptr.raw_c_str());
>> + EXPECT_EQ(len, const_ptr.raw_length());
>> + EXPECT_EQ(2, const_ptr.raw_nref());
>> + {
>> + bufferptr ptr(len);
>> + unsigned wasted = 1;
>> + ptr.set_length(ptr.length() - wasted * 2);
>> + ptr.set_offset(wasted);
>> + EXPECT_EQ(wasted * 2, ptr.wasted());
>> + }
>> +}
>> +
>> +TEST(BufferPtr, cmp) {
>> + bufferptr empty;
>> + bufferptr a("A", 1);
>> + bufferptr ab("AB", 2);
>> + bufferptr af("AF", 2);
>> + bufferptr acc("ACC", 3);
>> + EXPECT_GE(-1, empty.cmp(a));
>> + EXPECT_LE(1, a.cmp(empty));
>> + EXPECT_GE(-1, a.cmp(ab));
>> + EXPECT_LE(1, ab.cmp(a));
>> + EXPECT_EQ(0, ab.cmp(ab));
>> + EXPECT_GE(-1, ab.cmp(af));
>> + EXPECT_LE(1, af.cmp(ab));
>> + EXPECT_GE(-1, acc.cmp(af));
>> + EXPECT_LE(1, af.cmp(acc));
>> +}
>> +
>> +TEST(BufferPtr, is_zero) {
>> + char str[2] = { '\0', 'X' };
>> + {
>> + const bufferptr ptr(buffer::create_static(2, str));
>> + EXPECT_FALSE(ptr.is_zero());
>> + }
>> + {
>> + const bufferptr ptr(buffer::create_static(1, str));
>> + EXPECT_TRUE(ptr.is_zero());
>> + }
>> +}
>> +
>> +TEST(BufferPtr, copy_out) {
>> + {
>> + const bufferptr ptr;
>> + EXPECT_THROW(ptr.copy_out((unsigned)0, (unsigned)0, NULL), FailedAssertion);
>> + }
>> + {
>> + char in[] = "ABC";
>> + const bufferptr ptr(buffer::create_static(strlen(in), in));
>> + EXPECT_THROW(ptr.copy_out((unsigned)0, strlen(in) + 1, NULL), buffer::end_of_buffer);
>> + EXPECT_THROW(ptr.copy_out(strlen(in) + 1, (unsigned)0, NULL), buffer::end_of_buffer);
>> + char out[1] = { 'X' };
>> + ptr.copy_out((unsigned)1, (unsigned)1, out);
>> + EXPECT_EQ('B', out[0]);
>> + }
>> +}
>> +
>> +TEST(BufferPtr, copy_in) {
>> + {
>> + bufferptr ptr;
>> + EXPECT_THROW(ptr.copy_in((unsigned)0, (unsigned)0, NULL), FailedAssertion);
>> + }
>> + {
>> + char in[] = "ABCD";
>> + bufferptr ptr(2);
>> + EXPECT_THROW(ptr.copy_in((unsigned)0, strlen(in) + 1, NULL), FailedAssertion);
>> + EXPECT_THROW(ptr.copy_in(strlen(in) + 1, (unsigned)0, NULL), FailedAssertion);
>> + ptr.copy_in((unsigned)0, (unsigned)2, in);
>> + EXPECT_EQ(in[0], ptr[0]);
>> + EXPECT_EQ(in[1], ptr[1]);
>> + }
>> +}
>> +
>> +TEST(BufferPtr, append) {
>> + {
>> + bufferptr ptr;
>> + EXPECT_THROW(ptr.append('A'), FailedAssertion);
>> + EXPECT_THROW(ptr.append("B", (unsigned)1), FailedAssertion);
>> + }
>> + {
>> + bufferptr ptr(2);
>> + EXPECT_THROW(ptr.append('A'), FailedAssertion);
>> + EXPECT_THROW(ptr.append("B", (unsigned)1), FailedAssertion);
>> + ptr.set_length(0);
>> + ptr.append('A');
>> + EXPECT_EQ((unsigned)1, ptr.length());
>> + EXPECT_EQ('A', ptr[0]);
>> + ptr.append("B", (unsigned)1);
>> + EXPECT_EQ((unsigned)2, ptr.length());
>> + EXPECT_EQ('B', ptr[1]);
>> + }
>> +}
>> +
>> +TEST(BufferPtr, zero) {
>> + char str[] = "XXXX";
>> + bufferptr ptr(buffer::create_static(strlen(str), str));
>> + EXPECT_THROW(ptr.zero(ptr.length() + 1, 0), FailedAssertion);
>> + ptr.zero(1, 1);
>> + EXPECT_EQ('X', ptr[0]);
>> + EXPECT_EQ('\0', ptr[1]);
>> + EXPECT_EQ('X', ptr[2]);
>> + ptr.zero();
>> + EXPECT_EQ('\0', ptr[0]);
>> +}
>> +
>> +TEST(BufferPtr, ostream) {
>> + {
>> + bufferptr ptr;
>> + std::ostringstream stream;
>> + stream << ptr;
>> + EXPECT_GT(stream.str().size(), stream.str().find("buffer:ptr(0~0 no raw"));
>> + }
>> + {
>> + char str[] = "XXXX";
>> + bufferptr ptr(buffer::create_static(strlen(str), str));
>> + std::ostringstream stream;
>> + stream << ptr;
>> + EXPECT_GT(stream.str().size(), stream.str().find("len 4 nref 1)"));
>> + }
>> +}
>> +
>> +//
>> +// +---------+
>> +// | +-----+ |
>> +// list ptr | | | |
>> +// +----------+ +-----+ | | | |
>> +// | append_ >-------> >--------------------> | |
>> +// | buffer | +-----+ | | | |
>> +// +----------+ ptr | | | |
>> +// | _len | list +-----+ | | | |
>> +// +----------+ +------+ ,--->+ >-----> | |
>> +// | _buffers >----> >----- +-----+ | +-----+ |
>> +// +----------+ +----^-+ \ ptr | raw |
>> +// | last_p | / `-->+-----+ | +-----+ |
>> +// +--------+-+ / + >-----> | |
>> +// | ,- ,--->+-----+ | | | |
>> +// | / ,--- | | | |
>> +// | / ,--- | | | |
>> +// +-v--+-^--+--^+-------+ | | | |
>> +// | bl | ls | p | p_off >--------------->| | |
>> +// +----+----+-----+-----+ | +-----+ |
>> +// | | off >------------->| raw |
>> +// +---------------+-----+ | |
>> +// iterator +---------+
>> +//
>> +TEST(BufferListIterator, constructors) {
>> + //
>> + // iterator()
>> + //
>> + {
>> + buffer::list::iterator i;
>> + EXPECT_EQ((unsigned)0, i.get_off());
>> + }
>> +
>> + //
>> + // iterator(list *l, unsigned o=0)
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> +
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_EQ((unsigned)0, i.get_off());
>> + EXPECT_EQ('A', *i);
>> + }
>> + {
>> + bufferlist::iterator i(&bl, 1);
>> + EXPECT_EQ('B', *i);
>> + EXPECT_EQ((unsigned)2, i.get_remaining());
>> + }
>> + }
>> +
>> + //
>> + // iterator(list *l, unsigned o, std::list<ptr>::iterator ip, unsigned po)
>> + // not tested because of http://tracker.ceph.com/issues/4101
>> +
>> + //
>> + // iterator(const iterator& other)
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> + bufferlist::iterator i(&bl, 1);
>> + bufferlist::iterator j(i);
>> + EXPECT_EQ(*i, *j);
>> + ++j;
>> + EXPECT_NE(*i, *j);
>> + EXPECT_EQ('B', *i);
>> + EXPECT_EQ('C', *j);
>> + bl.c_str()[1] = 'X';
>> + j.advance(-1);
>> + EXPECT_EQ('X', *j);
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, operator_equal) {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> + bufferlist::iterator i(&bl, 1);
>> +
>> + i = i;
>> + EXPECT_EQ('B', *i);
>> + bufferlist::iterator j;
>> + j = i;
>> + EXPECT_EQ('B', *j);
>> +}
>> +
>> +TEST(BufferListIterator, get_off) {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> + bufferlist::iterator i(&bl, 1);
>> + EXPECT_EQ((unsigned)1, i.get_off());
>> +}
>> +
>> +TEST(BufferListIterator, get_remaining) {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> + bufferlist::iterator i(&bl, 1);
>> + EXPECT_EQ((unsigned)2, i.get_remaining());
>> +}
>> +
>> +TEST(BufferListIterator, end) {
>> + bufferlist bl;
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_TRUE(i.end());
>> + }
>> + bl.append("ABC", 3);
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_FALSE(i.end());
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, advance) {
>> + bufferlist bl;
>> + const std::string one("ABC");
>> + bl.append(bufferptr(one.c_str(), one.size()));
>> + const std::string two("DEF");
>> + bl.append(bufferptr(two.c_str(), two.size()));
>> +
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + }
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_THROW(i.advance(-1), buffer::end_of_buffer);
>> + }
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_EQ('A', *i);
>> + i.advance(1);
>> + EXPECT_EQ('B', *i);
>> + i.advance(3);
>> + EXPECT_EQ('E', *i);
>> + i.advance(-3);
>> + EXPECT_EQ('B', *i);
>> + i.advance(-1);
>> + EXPECT_EQ('A', *i);
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, seek) {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> + bufferlist::iterator i(&bl, 1);
>> + EXPECT_EQ('B', *i);
>> + i.seek(2);
>> + EXPECT_EQ('C', *i);
>> +}
>> +
>> +TEST(BufferListIterator, operator_star) {
>> + bufferlist bl;
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_THROW(*i, buffer::end_of_buffer);
>> + }
>> + bl.append("ABC", 3);
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_EQ('A', *i);
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + EXPECT_THROW(*i, buffer::end_of_buffer);
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, operator_plus_plus) {
>> + bufferlist bl;
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_THROW(++i, buffer::end_of_buffer);
>> + }
>> + bl.append("ABC", 3);
>> + {
>> + bufferlist::iterator i(&bl);
>> + ++i;
>> + EXPECT_EQ('B', *i);
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, get_current_ptr) {
>> + bufferlist bl;
>> + {
>> + bufferlist::iterator i(&bl);
>> + EXPECT_THROW(++i, buffer::end_of_buffer);
>> + }
>> + bl.append("ABC", 3);
>> + {
>> + bufferlist::iterator i(&bl, 1);
>> + const buffer::ptr ptr = i.get_current_ptr();
>> + EXPECT_EQ('B', ptr[0]);
>> + EXPECT_EQ((unsigned)1, ptr.offset());
>> + EXPECT_EQ((unsigned)2, ptr.length());
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, copy) {
>> + bufferlist bl;
>> + const char *expected = "ABC";
>> + bl.append(expected, 3);
>> + //
>> + // void copy(unsigned len, char *dest);
>> + //
>> + {
>> + char* copy = (char*)malloc(3);
>> + ::memset(copy, 'X', 3);
>> + bufferlist::iterator i(&bl);
>> + //
>> + // demonstrates that it seeks back to offset if p == ls->end()
>> + //
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + i.copy(2, copy);
>> + EXPECT_EQ(0, ::memcmp(copy, expected, 2));
>> + EXPECT_EQ('X', copy[2]);
>> + i.seek(0);
>> + i.copy(3, copy);
>> + EXPECT_EQ(0, ::memcmp(copy, expected, 3));
>> + }
>> + //
>> + // void buffer::list::iterator::copy(unsigned len, ptr &dest)
>> + //
>> + {
>> + bufferptr ptr;
>> + bufferlist::iterator i(&bl);
>> + i.copy(2, ptr);
>> + EXPECT_EQ((unsigned)2, ptr.length());
>> + EXPECT_EQ('A', ptr[0]);
>> + EXPECT_EQ('B', ptr[1]);
>> + }
>> + //
>> + // void buffer::list::iterator::copy(unsigned len, list &dest)
>> + //
>> + {
>> + bufferlist copy;
>> + bufferlist::iterator i(&bl);
>> + //
>> + // demonstrates that it seeks back to offset if p == ls->end()
>> + //
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + i.copy(2, copy);
>> + EXPECT_EQ(0, ::memcmp(copy.c_str(), expected, 2));
>> + i.seek(0);
>> + i.copy(3, copy);
>> + EXPECT_EQ('A', copy[0]);
>> + EXPECT_EQ('B', copy[1]);
>> + EXPECT_EQ('A', copy[2]);
>> + EXPECT_EQ('B', copy[3]);
>> + EXPECT_EQ('C', copy[4]);
>> + EXPECT_EQ((unsigned)(2 + 3), copy.length());
>> + }
>> + //
>> + // void buffer::list::iterator::copy_all(list &dest)
>> + //
>> + {
>> + bufferlist copy;
>> + bufferlist::iterator i(&bl);
>> + //
>> + // demonstrates that it seeks back to offset if p == ls->end()
>> + //
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + i.copy_all(copy);
>> + EXPECT_EQ('A', copy[0]);
>> + EXPECT_EQ('B', copy[1]);
>> + EXPECT_EQ('C', copy[2]);
>> + EXPECT_EQ((unsigned)3, copy.length());
>> + }
>> + //
>> + // void copy(unsigned len, std::string &dest)
>> + //
>> + {
>> + std::string copy;
>> + bufferlist::iterator i(&bl);
>> + //
>> + // demonstrates that it seeks back to offset if p == ls->end()
>> + //
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + i.copy(2, copy);
>> + EXPECT_EQ(0, ::memcmp(copy.c_str(), expected, 2));
>> + i.seek(0);
>> + i.copy(3, copy);
>> + EXPECT_EQ('A', copy[0]);
>> + EXPECT_EQ('B', copy[1]);
>> + EXPECT_EQ('A', copy[2]);
>> + EXPECT_EQ('B', copy[3]);
>> + EXPECT_EQ('C', copy[4]);
>> + EXPECT_EQ((unsigned)(2 + 3), copy.length());
>> + }
>> +}
>> +
>> +TEST(BufferListIterator, copy_in) {
>> + bufferlist bl;
>> + const char *existing = "XXX";
>> + bl.append(existing, 3);
>> + //
>> + // void buffer::list::iterator::copy_in(unsigned len, const char *src)
>> + //
>> + {
>> + bufferlist::iterator i(&bl);
>> + //
>> + // demonstrates that it seeks back to offset if p == ls->end()
>> + //
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + const char *expected = "ABC";
>> + i.copy_in(3, expected);
>> + EXPECT_EQ(0, ::memcmp(bl.c_str(), expected, 3));
>> + EXPECT_EQ('A', bl[0]);
>> + EXPECT_EQ('B', bl[1]);
>> + EXPECT_EQ('C', bl[2]);
>> + EXPECT_EQ((unsigned)3, bl.length());
>> + }
>> + //
>> + // void buffer::list::iterator::copy_in(unsigned len, const list& otherl)
>> + //
>> + {
>> + bufferlist::iterator i(&bl);
>> + //
>> + // demonstrates that it seeks back to offset if p == ls->end()
>> + //
>> + EXPECT_THROW(i.advance(200), buffer::end_of_buffer);
>> + bufferlist expected;
>> + expected.append("ABC", 3);
>> + i.copy_in(3, expected);
>> + EXPECT_EQ(0, ::memcmp(bl.c_str(), expected.c_str(), 3));
>> + EXPECT_EQ('A', bl[0]);
>> + EXPECT_EQ('B', bl[1]);
>> + EXPECT_EQ('C', bl[2]);
>> + EXPECT_EQ((unsigned)3, bl.length());
>> + }
>> +}
>> +
>> +TEST(BufferList, constructors) {
>> + //
>> + // list()
>> + //
>> + {
>> + bufferlist bl;
>> + ASSERT_EQ((unsigned)0, bl.length());
>> + }
>> + //
>> + // list(unsigned prealloc)
>> + //
>> + {
>> + bufferlist bl(1);
>> + ASSERT_EQ((unsigned)0, bl.length());
>> + bl.append('A');
>> + ASSERT_EQ('A', bl[0]);
>> + }
>> + //
>> + // list(const list& other)
>> + //
>> + {
>> + bufferlist bl(1);
>> + bl.append('A');
>> + ASSERT_EQ('A', bl[0]);
>> + bufferlist copy(bl);
>> + ASSERT_EQ('A', copy[0]);
>> + }
>> +}
>> +
>> +TEST(BufferList, operator_equal) {
>> + bufferlist bl;
>> + bl.append("ABC", 3);
>> + {
>> + std::string dest;
>> + bl.copy(1, 1, dest);
>> + ASSERT_EQ('B', dest[0]);
>> + }
>> + bufferlist copy;
>> + copy = bl;
>> + {
>> + std::string dest;
>> + copy.copy(1, 1, dest);
>> + ASSERT_EQ('B', dest[0]);
>> + }
>> +}
>> +
>> +TEST(BufferList, buffers) {
>> + bufferlist bl;
>> + ASSERT_EQ((unsigned)0, bl.buffers().size());
>> + bl.append('A');
>> + ASSERT_EQ((unsigned)1, bl.buffers().size());
>> +}
>> +
>> +TEST(BufferList, swap) {
>> + bufferlist b1;
>> + b1.append('A');
>> +
>> + bufferlist b2;
>> + b2.append('B');
>> +
>> + b1.swap(b2);
>> +
>> + std::string s1;
>> + b1.copy(0, 1, s1);
>> + ASSERT_EQ('B', s1[0]);
>> +
>> + std::string s2;
>> + b2.copy(0, 1, s2);
>> + ASSERT_EQ('A', s2[0]);
>> +}
>> +
>> +TEST(BufferList, length) {
>> + bufferlist bl;
>> + ASSERT_EQ((unsigned)0, bl.length());
>> + bl.append('A');
>> + ASSERT_EQ((unsigned)1, bl.length());
>> +}
>> +
>> +TEST(BufferList, contents_equal) {
>> + //
>> + // A BB
>> + // AB B
>> + //
>> + bufferlist bl1;
>> + bl1.append("A");
>> + bl1.append("BB");
>> + bufferlist bl2;
>> + ASSERT_FALSE(bl1.contents_equal(bl2)); // different length
>> + bl2.append("AB");
>> + bl2.append("B");
>> + ASSERT_TRUE(bl1.contents_equal(bl2)); // same length same content
>> + //
>> + // ABC
>> + //
>> + bufferlist bl3;
>> + bl3.append("ABC");
>> + ASSERT_FALSE(bl1.contents_equal(bl3)); // same length different content
>> +}
>> +
>> +TEST(BufferList, is_page_aligned) {
>> + {
>> + bufferlist bl;
>> + EXPECT_TRUE(bl.is_page_aligned());
>> + }
>> + {
>> + bufferlist bl;
>> + bufferptr ptr(2);
>> + ptr.set_offset(1);
>> + ptr.set_length(1);
>> + bl.append(ptr);
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + bl.rebuild_page_aligned();
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + }
>> + {
>> + bufferlist bl;
>> + bufferptr ptr(CEPH_PAGE_SIZE + 1);
>> + ptr.set_offset(1);
>> + ptr.set_length(CEPH_PAGE_SIZE);
>> + bl.append(ptr);
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + bl.rebuild_page_aligned();
>> + EXPECT_TRUE(bl.is_page_aligned());
>> + }
>> +}
>> +
>> +TEST(BufferList, is_n_page_sized) {
>> + {
>> + bufferlist bl;
>> + EXPECT_TRUE(bl.is_n_page_sized());
>> + }
>> + {
>> + bufferlist bl;
>> + bl.append_zero(1);
>> + EXPECT_FALSE(bl.is_n_page_sized());
>> + }
>> + {
>> + bufferlist bl;
>> + bl.append_zero(CEPH_PAGE_SIZE);
>> + EXPECT_TRUE(bl.is_n_page_sized());
>> + }
>> +}
>> +
>> +TEST(BufferList, is_zero) {
>> + {
>> + bufferlist bl;
>> + EXPECT_TRUE(bl.is_zero());
>> + }
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + EXPECT_FALSE(bl.is_zero());
>> + }
>> + {
>> + bufferlist bl;
>> + bl.append_zero(1);
>> + EXPECT_TRUE(bl.is_zero());
>> + }
>> +}
>> +
>> +TEST(BufferList, clear) {
>> + bufferlist bl;
>> + unsigned len = 17;
>> + bl.append_zero(len);
>> + bl.clear();
>> + EXPECT_EQ((unsigned)0, bl.length());
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> +}
>> +
>> +TEST(BufferList, push_front) {
>> + //
>> + // void push_front(ptr& bp)
>> + //
>> + {
>> + bufferlist bl;
>> + bufferptr ptr;
>> + bl.push_front(ptr);
>> + EXPECT_EQ((unsigned)0, bl.length());
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> + }
>> + unsigned len = 17;
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + bufferptr ptr(len);
>> + ptr.c_str()[0] = 'B';
>> + bl.push_front(ptr);
>> + EXPECT_EQ((unsigned)(1 + len), bl.length());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ('B', bl.buffers().front()[0]);
>> + EXPECT_EQ(ptr.get_raw(), bl.buffers().front().get_raw());
>> + }
>> + //
>> + // void push_front(raw *r)
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + bufferptr ptr(len);
>> + ptr.c_str()[0] = 'B';
>> + bl.push_front(ptr.get_raw());
>> + EXPECT_EQ((unsigned)(1 + len), bl.length());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ('B', bl.buffers().front()[0]);
>> + EXPECT_EQ(ptr.get_raw(), bl.buffers().front().get_raw());
>> + }
>> +}
>> +
>> +TEST(BufferList, push_back) {
>> + //
>> + // void push_back(ptr& bp)
>> + //
>> + {
>> + bufferlist bl;
>> + bufferptr ptr;
>> + bl.push_back(ptr);
>> + EXPECT_EQ((unsigned)0, bl.length());
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> + }
>> + unsigned len = 17;
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + bufferptr ptr(len);
>> + ptr.c_str()[0] = 'B';
>> + bl.push_back(ptr);
>> + EXPECT_EQ((unsigned)(1 + len), bl.length());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ('B', bl.buffers().back()[0]);
>> + EXPECT_EQ(ptr.get_raw(), bl.buffers().back().get_raw());
>> + }
>> + //
>> + // void push_back(raw *r)
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + bufferptr ptr(len);
>> + ptr.c_str()[0] = 'B';
>> + bl.push_back(ptr.get_raw());
>> + EXPECT_EQ((unsigned)(1 + len), bl.length());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ('B', bl.buffers().back()[0]);
>> + EXPECT_EQ(ptr.get_raw(), bl.buffers().back().get_raw());
>> + }
>> +}
>> +
>> +TEST(BufferList, is_contiguous) {
>> + bufferlist bl;
>> + EXPECT_TRUE(bl.is_contiguous());
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> + bl.append('A');
>> + EXPECT_TRUE(bl.is_contiguous());
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + bufferptr ptr(1);
>> + bl.push_back(ptr);
>> + EXPECT_FALSE(bl.is_contiguous());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> +}
>> +
>> +TEST(BufferList, rebuild) {
>> + {
>> + bufferlist bl;
>> + bufferptr ptr(2);
>> + ptr.set_offset(1);
>> + ptr.set_length(1);
>> + bl.append(ptr);
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + bl.rebuild();
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + }
>> + {
>> + bufferlist bl;
>> + const std::string str(CEPH_PAGE_SIZE, 'X');
>> + bl.append(str.c_str(), str.size());
>> + bl.append(str.c_str(), str.size());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_TRUE(bl.is_page_aligned());
>> + bl.rebuild();
>> + EXPECT_TRUE(bl.is_page_aligned());
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + }
>> +}
>> +
>> +TEST(BufferList, rebuild_page_aligned) {
>> + {
>> + bufferlist bl;
>> + {
>> + bufferptr ptr(CEPH_PAGE_SIZE + 1);
>> + ptr.set_offset(1);
>> + ptr.set_length(CEPH_PAGE_SIZE);
>> + bl.append(ptr);
>> + }
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + bl.rebuild_page_aligned();
>> + EXPECT_TRUE(bl.is_page_aligned());
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + }
>> + {
>> + bufferlist bl;
>> + {
>> + bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE));
>> + bl.append(ptr);
>> + }
>> + {
>> + bufferptr ptr(CEPH_PAGE_SIZE + 1);
>> + bl.append(ptr);
>> + }
>> + {
>> + bufferptr ptr(2);
>> + ptr.set_offset(1);
>> + ptr.set_length(1);
>> + bl.append(ptr);
>> + }
>> + {
>> + bufferptr ptr(CEPH_PAGE_SIZE - 2);
>> + bl.append(ptr);
>> + }
>> + {
>> + bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE));
>> + bl.append(ptr);
>> + }
>> + {
>> + bufferptr ptr(CEPH_PAGE_SIZE + 1);
>> + ptr.set_offset(1);
>> + ptr.set_length(CEPH_PAGE_SIZE);
>> + bl.append(ptr);
>> + }
>> + EXPECT_EQ((unsigned)6, bl.buffers().size());
>> + EXPECT_TRUE((bl.length() & ~CEPH_PAGE_MASK) == 0);
>> + EXPECT_FALSE(bl.is_page_aligned());
>> + bl.rebuild_page_aligned();
>> + EXPECT_TRUE(bl.is_page_aligned());
>> + EXPECT_EQ((unsigned)4, bl.buffers().size());
>> + }
>> +}
>> +
>> +TEST(BufferList, claim) {
>> + bufferlist from;
>> + {
>> + bufferptr ptr(2);
>> + from.append(ptr);
>> + }
>> + bufferlist to;
>> + {
>> + bufferptr ptr(4);
>> + to.append(ptr);
>> + }
>> + EXPECT_EQ((unsigned)4, to.length());
>> + EXPECT_EQ((unsigned)1, to.buffers().size());
>> + to.claim(from);
>> + EXPECT_EQ((unsigned)2, to.length());
>> + EXPECT_EQ((unsigned)1, to.buffers().size());
>> + EXPECT_EQ((unsigned)0, from.buffers().size());
>> + EXPECT_EQ((unsigned)0, from.length());
>> +}
>> +
>> +TEST(BufferList, claim_append) {
>> + bufferlist from;
>> + {
>> + bufferptr ptr(2);
>> + from.append(ptr);
>> + }
>> + bufferlist to;
>> + {
>> + bufferptr ptr(4);
>> + to.append(ptr);
>> + }
>> + EXPECT_EQ((unsigned)4, to.length());
>> + EXPECT_EQ((unsigned)1, to.buffers().size());
>> + to.claim_append(from);
>> + EXPECT_EQ((unsigned)(4 + 2), to.length());
>> + EXPECT_EQ((unsigned)4, to.buffers().front().length());
>> + EXPECT_EQ((unsigned)2, to.buffers().back().length());
>> + EXPECT_EQ((unsigned)2, to.buffers().size());
>> + EXPECT_EQ((unsigned)0, from.buffers().size());
>> + EXPECT_EQ((unsigned)0, from.length());
>> +}
>> +
>> +TEST(BufferList, claim_prepend) {
>> + bufferlist from;
>> + {
>> + bufferptr ptr(2);
>> + from.append(ptr);
>> + }
>> + bufferlist to;
>> + {
>> + bufferptr ptr(4);
>> + to.append(ptr);
>> + }
>> + EXPECT_EQ((unsigned)4, to.length());
>> + EXPECT_EQ((unsigned)1, to.buffers().size());
>> + to.claim_prepend(from);
>> + EXPECT_EQ((unsigned)(2 + 4), to.length());
>> + EXPECT_EQ((unsigned)2, to.buffers().front().length());
>> + EXPECT_EQ((unsigned)4, to.buffers().back().length());
>> + EXPECT_EQ((unsigned)2, to.buffers().size());
>> + EXPECT_EQ((unsigned)0, from.buffers().size());
>> + EXPECT_EQ((unsigned)0, from.length());
>> +}
>> +
>> +TEST(BufferList, begin) {
>> + bufferlist bl;
>> + bl.append("ABC");
>> + bufferlist::iterator i = bl.begin();
>> + EXPECT_EQ('A', *i);
>> +}
>> +
>> +TEST(BufferList, end) {
>> + bufferlist bl;
>> + bl.append("ABC");
>> + bufferlist::iterator i = bl.end();
>> + i.advance(-1);
>> + EXPECT_EQ('C', *i);
>> +}
>> +
>> +TEST(BufferList, copy) {
>> + //
>> + // void copy(unsigned off, unsigned len, char *dest) const;
>> + //
>> + {
>> + bufferlist bl;
>> + EXPECT_THROW(bl.copy((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer);
>> + const char *expected = "ABC";
>> + bl.append(expected);
>> + char *dest = new char[2];
>> + bl.copy(1, 2, dest);
>> + EXPECT_EQ(0, ::memcmp(expected + 1, dest, 2));
>> + delete [] dest;
>> + }
>> + //
>> + // void copy(unsigned off, unsigned len, list &dest) const;
>> + //
>> + {
>> + bufferlist bl;
>> + bufferlist dest;
>> + EXPECT_THROW(bl.copy((unsigned)100, (unsigned)100, dest), buffer::end_of_buffer);
>> + const char *expected = "ABC";
>> + bl.append(expected);
>> + bl.copy(1, 2, dest);
>> + EXPECT_EQ(0, ::memcmp(expected + 1, dest.c_str(), 2));
>> + }
>> + //
>> + // void copy(unsigned off, unsigned len, std::string &dest) const;
>> + //
>> + {
>> + bufferlist bl;
>> + std::string dest;
>> + EXPECT_THROW(bl.copy((unsigned)100, (unsigned)100, dest), buffer::end_of_buffer);
>> + const char *expected = "ABC";
>> + bl.append(expected);
>> + bl.copy(1, 2, dest);
>> + EXPECT_EQ(0, ::memcmp(expected + 1, dest.c_str(), 2));
>> + }
>> +}
>> +
>> +TEST(BufferList, copy_in) {
>> + //
>> + // void copy_in(unsigned off, unsigned len, const char *src);
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append("XXX");
>> + EXPECT_THROW(bl.copy_in((unsigned)100, (unsigned)100, (char*)0), buffer::end_of_buffer);
>> + bl.copy_in(1, 2, "AB");
>> + EXPECT_EQ(0, ::memcmp("XAB", bl.c_str(), 3));
>> + }
>> + //
>> + // void copy_in(unsigned off, unsigned len, const list& src);
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append("XXX");
>> + bufferlist src;
>> + src.append("ABC");
>> + EXPECT_THROW(bl.copy_in((unsigned)100, (unsigned)100, src), buffer::end_of_buffer);
>> + bl.copy_in(1, 2, src);
>> + EXPECT_EQ(0, ::memcmp("XAB", bl.c_str(), 3));
>> + }
>> }
>>
>> -TEST(BufferList, zero) {
>> +TEST(BufferList, append) {
>> //
>> - // void zero()
>> + // void append(char c);
>> //
>> {
>> bufferlist bl;
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> bl.append('A');
>> - EXPECT_EQ('A', bl[0]);
>> - bl.zero();
>> - EXPECT_EQ('\0', bl[0]);
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_TRUE(bl.is_page_aligned());
>> }
>> //
>> - // void zero(unsigned o, unsigned l)
>> + // void append(const char *data, unsigned len);
>> + //
>> + {
>> + bufferlist bl(CEPH_PAGE_SIZE);
>> + std::string str(CEPH_PAGE_SIZE * 2, 'X');
>> + bl.append(str.c_str(), str.size());
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ(CEPH_PAGE_SIZE, bl.buffers().front().length());
>> + EXPECT_EQ(CEPH_PAGE_SIZE, bl.buffers().back().length());
>> + }
>> + //
>> + // void append(const std::string& s);
>> + //
>> + {
>> + bufferlist bl(CEPH_PAGE_SIZE);
>> + std::string str(CEPH_PAGE_SIZE * 2, 'X');
>> + bl.append(str);
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ(CEPH_PAGE_SIZE, bl.buffers().front().length());
>> + EXPECT_EQ(CEPH_PAGE_SIZE, bl.buffers().back().length());
>> + }
>> + //
>> + // void append(const ptr& bp);
>> + //
>> + {
>> + bufferlist bl;
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> + EXPECT_EQ((unsigned)0, bl.length());
>> + {
>> + bufferptr ptr;
>> + bl.append(ptr);
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> + EXPECT_EQ((unsigned)0, bl.length());
>> + }
>> + {
>> + bufferptr ptr(3);
>> + bl.append(ptr);
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_EQ((unsigned)3, bl.length());
>> + }
>> + }
>> + //
>> + // void append(const ptr& bp, unsigned off, unsigned len);
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + bufferptr back(bl.buffers().back());
>> + bufferptr in(back);
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_EQ((unsigned)1, bl.length());
>> + EXPECT_THROW(bl.append(in, (unsigned)100, (unsigned)100), FailedAssertion);
>> + EXPECT_LT((unsigned)0, in.unused_tail_length());
>> + in.append('B');
>> + bl.append(in, back.end(), 1);
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_EQ((unsigned)2, bl.length());
>> + EXPECT_EQ('B', bl[1]);
>> + }
>> + {
>> + bufferlist bl;
>> + EXPECT_EQ((unsigned)0, bl.buffers().size());
>> + EXPECT_EQ((unsigned)0, bl.length());
>> + bufferptr ptr(2);
>> + ptr.set_length(0);
>> + ptr.append("AB", 2);
>> + bl.append(ptr, 1, 1);
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_EQ((unsigned)1, bl.length());
>> + }
>> + //
>> + // void append(const list& bl);
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + bufferlist other;
>> + other.append('B');
>> + bl.append(other);
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ('B', bl[1]);
>> + }
>> + //
>> + // void append(std::istream& in);
>> //
>> + {
>> + bufferlist bl;
>> + std::string expected("ABC\n\nDEF\n");
>> + std::istringstream is("ABC\n\nDEF");
>> + bl.append(is);
>> + EXPECT_EQ(0, ::memcmp(expected.c_str(), bl.c_str(), expected.size()));
>> + EXPECT_EQ(expected.size(), bl.length());
>> + }
>> +}
>> +
>> +TEST(BufferList, append_zero) {
>> + bufferlist bl;
>> + bl.append('A');
>> + EXPECT_EQ((unsigned)1, bl.buffers().size());
>> + EXPECT_EQ((unsigned)1, bl.length());
>> + bl.append_zero(1);
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ((unsigned)2, bl.length());
>> + EXPECT_EQ('\0', bl[1]);
>> +}
>> +
>> +TEST(BufferList, operator_brackets) {
>> + bufferlist bl;
>> + EXPECT_THROW(bl[1], buffer::end_of_buffer);
>> + bl.append('A');
>> + bufferlist other;
>> + other.append('B');
>> + bl.append(other);
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ('B', bl[1]);
>> +}
>> +
>> +TEST(BufferList, c_str) {
>> + bufferlist bl;
>> + EXPECT_EQ((const char*)NULL, bl.c_str());
>> + bl.append('A');
>> + bufferlist other;
>> + other.append('B');
>> + bl.append(other);
>> + EXPECT_EQ((unsigned)2, bl.buffers().size());
>> + EXPECT_EQ(0, ::memcmp("AB", bl.c_str(), 2));
>> +}
>> +
>> +TEST(BufferList, substr_of) {
>> + bufferlist bl;
>> + EXPECT_THROW(bl.substr_of(bl, 1, 1), buffer::end_of_buffer);
>> const char *s[] = {
>> "ABC",
>> "DEF",
>> "GHI",
>> - "KLM"
>> + "JKL"
>> };
>> - {
>> - bufferlist bl;
>> - bufferptr ptr(s[0], strlen(s[0]));
>> + for (unsigned i = 0; i < 4; i++) {
>> + bufferptr ptr(s[i], strlen(s[i]));
>> bl.push_back(ptr);
>> - bl.zero((unsigned)0, (unsigned)1);
>> - EXPECT_EQ(0, ::memcmp("\0BC", bl.c_str(), 3));
>> }
>> - {
>> - bufferlist bl;
>> - for (unsigned i = 0; i < 4; i++) {
>> - bufferptr ptr(s[i], strlen(s[i]));
>> - bl.push_back(ptr);
>> - }
>> - EXPECT_THROW(bl.zero((unsigned)0, (unsigned)2000), FailedAssertion);
>> - bl.zero((unsigned)2, (unsigned)5);
>> - EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl.c_str(), 9));
>> + EXPECT_EQ((unsigned)4, bl.buffers().size());
>> +
>> + bufferlist other;
>> + other.append("TO BE CLEARED");
>> + other.substr_of(bl, 4, 4);
>> + EXPECT_EQ((unsigned)2, other.buffers().size());
>> + EXPECT_EQ((unsigned)4, other.length());
>> + EXPECT_EQ(0, ::memcmp("EFGH", other.c_str(), 4));
>> +}
>> +
>> +TEST(BufferList, splice) {
>> + bufferlist bl;
>> + EXPECT_THROW(bl.splice(1, 1), buffer::end_of_buffer);
>> + const char *s[] = {
>> + "ABC",
>> + "DEF",
>> + "GHI",
>> + "JKL"
>> + };
>> + for (unsigned i = 0; i < 4; i++) {
>> + bufferptr ptr(s[i], strlen(s[i]));
>> + bl.push_back(ptr);
>> }
>> + EXPECT_EQ((unsigned)4, bl.buffers().size());
>> + EXPECT_THROW(bl.splice(0, 0), FailedAssertion);
>> +
>> + bufferlist other;
>> + other.append('X');
>> + bl.splice(4, 4, &other);
>> + EXPECT_EQ((unsigned)3, other.buffers().size());
>> + EXPECT_EQ((unsigned)5, other.length());
>> + EXPECT_EQ(0, ::memcmp("XEFGH", other.c_str(), other.length()));
>> + EXPECT_EQ((unsigned)8, bl.length());
>> {
>> - bufferlist bl;
>> - for (unsigned i = 0; i < 4; i++) {
>> - bufferptr ptr(s[i], strlen(s[i]));
>> - bl.push_back(ptr);
>> - }
>> - bl.zero((unsigned)3, (unsigned)3);
>> - EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl.c_str(), 9));
>> + bufferlist tmp(bl);
>> + EXPECT_EQ(0, ::memcmp("ABCDIJKL", tmp.c_str(), tmp.length()));
>> + }
>> +
>> + bl.splice(4, 4);
>> + EXPECT_EQ((unsigned)4, bl.length());
>> + EXPECT_EQ(0, ::memcmp("ABCD", bl.c_str(), bl.length()));
>> +}
>> +
>> +TEST(BufferList, write) {
>> + std::ostringstream stream;
>> + bufferlist bl;
>> + bl.append("ABC");
>> + bl.write(1, 2, stream);
>> + EXPECT_EQ("BC", stream.str());
>> +}
>> +
>> +TEST(BufferList, encode_base64) {
>> + bufferlist bl;
>> + bl.append("ABCD");
>> + bufferlist other;
>> + bl.encode_base64(other);
>> + const char *expected = "QUJDRA==";
>> + EXPECT_EQ(0, ::memcmp(expected, other.c_str(), strlen(expected)));
>> +}
>> +
>> +TEST(BufferList, decode_base64) {
>> + bufferlist bl;
>> + bl.append("QUJDRA==");
>> + bufferlist other;
>> + other.decode_base64(bl);
>> + const char *expected = "ABCD";
>> + EXPECT_EQ(0, ::memcmp(expected, other.c_str(), strlen(expected)));
>> + bufferlist malformed;
>> + malformed.append("QUJDRA");
>> + EXPECT_THROW(other.decode_base64(malformed), buffer::malformed_input);
>> +}
>> +
>> +TEST(BufferList, hexdump) {
>> + bufferlist bl;
>> + std::ostringstream stream;
>> + bl.append("013245678901234\0006789012345678901234", 32);
>> + bl.hexdump(stream);
>> + EXPECT_EQ("0000 : 30 31 33 32 34 35 36 37 38 39 30 31 32 33 34 00 : 013245678901234.\n"
>> + "0010 : 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 : 6789012345678901\n",
>> + stream.str());
>> +}
>> +
>> +TEST(BufferList, read_file) {
>> + std::string error;
>> + bufferlist bl;
>> + ::unlink("testfile");
>> + EXPECT_EQ(-ENOENT, bl.read_file("UNLIKELY", &error));
>> + ::system("echo ABC > testfile ; chmod 0 testfile");
>> + EXPECT_EQ(-EACCES, bl.read_file("testfile", &error));
>> + ::system("chmod +r testfile");
>> + EXPECT_EQ(0, bl.read_file("testfile", &error));
>> + ::unlink("testfile");
>> + EXPECT_EQ((unsigned)4, bl.length());
>> + std::string actual(bl.c_str(), bl.length());
>> + EXPECT_EQ("ABC\n", actual);
>> +}
>> +
>> +TEST(BufferList, read_fd) {
>> + unsigned len = 4;
>> + ::unlink("testfile");
>> + ::system("echo ABC > testfile");
>> + int fd = -1;
>> + bufferlist bl;
>> + EXPECT_EQ(-EBADF, bl.read_fd(fd, len));
>> + fd = ::open("testfile", O_RDONLY);
>> + EXPECT_EQ(len, bl.read_fd(fd, len));
>> + EXPECT_EQ(len, bl.length());
>> + EXPECT_EQ(CEPH_PAGE_SIZE - len, bl.buffers().front().unused_tail_length());
>> + ::close(fd);
>> + ::unlink("testfile");
>> +}
>> +
>> +TEST(BufferList, write_file) {
>> + ::unlink("testfile");
>> + int mode = 0600;
>> + bufferlist bl;
>> + EXPECT_EQ(-ENOENT, bl.write_file("un/like/ly", mode));
>> + bl.append("ABC");
>> + EXPECT_EQ(0, bl.write_file("testfile", mode));
>> + struct stat st;
>> + memset(&st, 0, sizeof(st));
>> + ::stat("testfile", &st);
>> + EXPECT_EQ((unsigned)(mode | S_IFREG), st.st_mode);
>> + ::unlink("testfile");
>> +}
>> +
>> +TEST(BufferList, write_fd) {
>> + ::unlink("testfile");
>> + int fd = ::open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0600);
>> + bufferlist bl;
>> + for (unsigned i = 0; i < IOV_MAX * 2; i++) {
>> + bufferptr ptr("A", 1);
>> + bl.push_back(ptr);
>> }
>> + EXPECT_EQ(0, bl.write_fd(fd));
>> + ::close(fd);
>> + struct stat st;
>> + memset(&st, 0, sizeof(st));
>> + ::stat("testfile", &st);
>> + EXPECT_EQ(IOV_MAX * 2, st.st_size);
>> + ::unlink("testfile");
>> +}
>> +
>> +TEST(BufferList, crc32c) {
>> + bufferlist bl;
>> + __u32 crc = 0;
>> + bl.append("A");
>> + crc = bl.crc32c(crc);
>> + EXPECT_EQ((unsigned)0xB3109EBF, crc);
>> + crc = bl.crc32c(crc);
>> + EXPECT_EQ((unsigned)0x5FA5C0CC, crc);
>> }
>>
>> TEST(BufferList, compare) {
>> @@ -121,6 +1694,72 @@ TEST(BufferList, compare) {
>> ASSERT_TRUE(ab == ab);
>> }
>>
>> +TEST(BufferList, ostream) {
>> + std::ostringstream stream;
>> + bufferlist bl;
>> + const char *s[] = {
>> + "ABC",
>> + "DEF"
>> + };
>> + for (unsigned i = 0; i < 2; i++) {
>> + bufferptr ptr(s[i], strlen(s[i]));
>> + bl.push_back(ptr);
>> + }
>> + stream << bl;
>> + std::cerr << stream.str() << std::endl;
>> + EXPECT_GT(stream.str().size(), stream.str().find("list(len=6,"));
>> + EXPECT_GT(stream.str().size(), stream.str().find("len 3 nref 1),\n"));
>> + EXPECT_GT(stream.str().size(), stream.str().find("len 3 nref 1)\n"));
>> +}
>> +
>> +TEST(BufferList, zero) {
>> + //
>> + // void zero()
>> + //
>> + {
>> + bufferlist bl;
>> + bl.append('A');
>> + EXPECT_EQ('A', bl[0]);
>> + bl.zero();
>> + EXPECT_EQ('\0', bl[0]);
>> + }
>> + //
>> + // void zero(unsigned o, unsigned l)
>> + //
>> + const char *s[] = {
>> + "ABC",
>> + "DEF",
>> + "GHI",
>> + "KLM"
>> + };
>> + {
>> + bufferlist bl;
>> + bufferptr ptr(s[0], strlen(s[0]));
>> + bl.push_back(ptr);
>> + bl.zero((unsigned)0, (unsigned)1);
>> + EXPECT_EQ(0, ::memcmp("\0BC", bl.c_str(), 3));
>> + }
>> + {
>> + bufferlist bl;
>> + for (unsigned i = 0; i < 4; i++) {
>> + bufferptr ptr(s[i], strlen(s[i]));
>> + bl.push_back(ptr);
>> + }
>> + EXPECT_THROW(bl.zero((unsigned)0, (unsigned)2000), FailedAssertion);
>> + bl.zero((unsigned)2, (unsigned)5);
>> + EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl.c_str(), 9));
>> + }
>> + {
>> + bufferlist bl;
>> + for (unsigned i = 0; i < 4; i++) {
>> + bufferptr ptr(s[i], strlen(s[i]));
>> + bl.push_back(ptr);
>> + }
>> + bl.zero((unsigned)3, (unsigned)3);
>> + EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl.c_str(), 9));
>> + }
>> +}
>> +
>> TEST(BufferList, EmptyAppend) {
>> bufferlist bl;
>> bufferptr ptr;
>> @@ -151,54 +1790,6 @@ TEST(BufferList, TestPtrAppend) {
>> ASSERT_EQ(memcmp(bl.c_str(), correct, curpos), 0);
>> }
>>
>> -TEST(BufferList, ptr_assignment) {
>> - unsigned len = 17;
>> - //
>> - // override a bufferptr set with the same raw
>> - //
>> - {
>> - bufferptr original(len);
>> - bufferptr same_raw(original.get_raw());
>> - unsigned offset = 5;
>> - unsigned length = len - offset;
>> - original.set_offset(offset);
>> - original.set_length(length);
>> - same_raw = original;
>> - ASSERT_EQ(2, original.raw_nref());
>> - ASSERT_EQ(same_raw.get_raw(), original.get_raw());
>> - ASSERT_EQ(same_raw.offset(), original.offset());
>> - ASSERT_EQ(same_raw.length(), original.length());
>> - }
>> -
>> - //
>> - // self assignment is a noop
>> - //
>> - {
>> - bufferptr original(len);
>> - original = original;
>> - ASSERT_EQ(1, original.raw_nref());
>> - ASSERT_EQ((unsigned)0, original.offset());
>> - ASSERT_EQ(len, original.length());
>> - }
>> -
>> - //
>> - // a copy points to the same raw
>> - //
>> - {
>> - bufferptr original(len);
>> - unsigned offset = 5;
>> - unsigned length = len - offset;
>> - original.set_offset(offset);
>> - original.set_length(length);
>> - bufferptr ptr;
>> - ptr = original;
>> - ASSERT_EQ(2, original.raw_nref());
>> - ASSERT_EQ(ptr.get_raw(), original.get_raw());
>> - ASSERT_EQ(original.offset(), ptr.offset());
>> - ASSERT_EQ(original.length(), ptr.length());
>> - }
>> -}
>> -
>> TEST(BufferList, TestDirectAppend) {
>> bufferlist bl;
>> char correct[MAX_TEST];
>> @@ -234,3 +1825,29 @@ TEST(BufferList, TestCopyAll) {
>> bl2.copy(0, BIG_SZ, (char*)big2);
>> ASSERT_EQ(memcmp(big.get(), big2, BIG_SZ), 0);
>> }
>> +
>> +TEST(BufferHash, all) {
>> + {
>> + bufferlist bl;
>> + bl.append("A");
>> + bufferhash hash;
>> + EXPECT_EQ((unsigned)0, hash.digest());
>> + hash.update(bl);
>> + EXPECT_EQ((unsigned)0xB3109EBF, hash.digest());
>> + hash.update(bl);
>> + EXPECT_EQ((unsigned)0x5FA5C0CC, hash.digest());
>> + }
>> + {
>> + bufferlist bl;
>> + bl.append("A");
>> + bufferhash hash;
>> + EXPECT_EQ((unsigned)0, hash.digest());
>> + bufferhash& returned_hash = hash << bl;
>> + EXPECT_EQ(&returned_hash, &hash);
>> + EXPECT_EQ((unsigned)0xB3109EBF, hash.digest());
>> + }
>> +}
>> +
>> +// Local Variables:
>> +// compile-command: "cd .. ; make unittest_bufferlist ; ulimit -s unlimited ; CEPH_BUFFER_TRACK=true valgrind --max-stackframe=20000000 --tool=memcheck ./unittest_bufferlist # --gtest_filter=BufferList.constructors"
>> +// End:
>> diff --git a/src/unittest_bufferlist.sh b/src/unittest_bufferlist.sh
>> new file mode 100755
>> index 0000000..0f05afe
>> --- /dev/null
>> +++ b/src/unittest_bufferlist.sh
>> @@ -0,0 +1,19 @@
>> +#!/bin/bash
>> +#
>> +# Ceph - scalable distributed file system
>> +#
>> +# Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
>> +#
>> +# Author: Loic Dachary <loic@dachary.org>
>> +#
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU Library Public License as published by
>> +# the Free Software Foundation; either version 2, or (at your option)
>> +# any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> +# GNU Library Public License for more details.
>> +#
>> +CEPH_BUFFER_TRACK=true ./unittest_bufferlist
>> --
>> 1.7.10.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>>
--
Loïc Dachary, Artisan Logiciel Libre
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
prev parent reply other threads:[~2013-02-18 7:17 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-17 19:38 [PATCH] unit tests for src/common/buffer.{cc,h} Loic Dachary
2013-02-18 5:48 ` Sage Weil
2013-02-18 7:17 ` Loic Dachary [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5121D5A0.5000807@dachary.org \
--to=loic@dachary.org \
--cc=ceph-devel@vger.kernel.org \
--cc=sage@inktank.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.