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@xxxxxxxxxxx> >> --- >> 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@xxxxxxxxxxxxx> >> + * >> + * Author: Loic Dachary <loic@xxxxxxxxxxx> >> + * >> + * 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@xxxxxxxxxxxxx> >> +# >> +# Author: Loic Dachary <loic@xxxxxxxxxxx> >> +# >> +# 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@xxxxxxxxxxxxxxx >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> >> -- Loïc Dachary, Artisan Logiciel Libre
Attachment:
signature.asc
Description: OpenPGP digital signature