22 #include <boost/random.hpp> 35 using std::unique_ptr;
45 memcpy(buf->
writableData() - str.size(), str.data(), str.size());
50 unique_ptr<IOBuf> buf(IOBuf::create(100));
68 const char* p =
reinterpret_cast<const char*
>(buf->
data());
78 unique_ptr<IOBuf> iobuf(IOBuf::create(requestedCapacity));
108 unique_ptr<IOBuf> iobuf1(IOBuf::takeOwnership(buf1, size1));
117 unique_ptr<IOBuf> iobuf2(
131 unique_ptr<IOBuf> iobuf3(IOBuf::takeOwnership(
147 IOBuf::TAKE_OWNERSHIP,
171 unique_ptr<IOBuf> iobuf1(IOBuf::wrapBuffer(buf1, size1));
178 unique_ptr<uint8_t[]> buf2(
new uint8_t[size2]);
179 unique_ptr<IOBuf> iobuf2(IOBuf::wrapBuffer(buf2.get(), size2));
186 unique_ptr<uint8_t[]> buf3(
new uint8_t[size3]);
187 IOBuf iobuf3(IOBuf::WRAP_BUFFER, buf3.get(), size3);
194 unique_ptr<uint8_t[]> buf4(
new uint8_t[size4]);
195 IOBuf iobuf4 = IOBuf::wrapBufferAsValue(buf4.get(), size4);
206 auto buf = IOBuf::createCombined(256);
214 auto bufA = IOBuf::createCombined(256);
216 auto bufB = bufA->clone();
228 auto buf = IOBuf::createCombined(256);
229 buf->reserve(0, buf->capacity() + 100);
235 auto testSwap = [](
bool resetAFirst) {
236 auto bufA = IOBuf::createCombined(256);
238 auto bufB = bufA->clone();
258 for (
uint32_t n = 0; n < length; ++n) {
259 buf[n] =
static_cast<uint8_t>(gen() & 0xff);
276 for (
uint32_t n = 0; n < length; ++n) {
278 if (buf[n] == expected) {
282 if (numDifferences == 0) {
284 firstDiffExpected = expected;
290 if (numDifferences > 0) {
294 static_cast<int>(buf[firstDiffIndex]),
295 static_cast<int>(firstDiffExpected));
304 checkBuf(buf.data(), buf.size(), gen);
311 current = current->
next();
312 }
while (current != buf);
317 boost::mt19937 gen(fillSeed);
321 unique_ptr<IOBuf> iob1(IOBuf::create(2048));
327 unique_ptr<IOBuf> iob2(IOBuf::create(20));
334 unique_ptr<IOBuf> iob3(IOBuf::wrapBuffer(localbuf,
sizeof(localbuf)));
339 fillBuf(heapBuf, heapBufSize, gen);
340 unique_ptr<IOBuf> iob4(IOBuf::takeOwnership(heapBuf, heapBufSize));
346 fillBuf(arrayBuf, arrayBufSize, gen);
348 unique_ptr<IOBuf> iob5(IOBuf::takeOwnership(
366 IOBuf* iob2ptr = iob2.get();
367 IOBuf* iob3ptr = iob3.get();
368 IOBuf* iob4ptr = iob4.get();
369 IOBuf* iob5ptr = iob5.get();
394 std::size_t fullLength =
395 (iob1->
length() + iob2ptr->length() + iob3ptr->
length() +
416 for (
auto buf : *iob1) {
423 unique_ptr<IOBuf> iob4clone = iob4ptr->
cloneOne();
455 unique_ptr<IOBuf> iob3clone = iob3ptr->
cloneOne();
473 unique_ptr<IOBuf> chainClone = iob1->clone();
475 EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
490 chainClone->unshare();
495 EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
504 chainClone = iob1->clone();
518 EXPECT_EQ(5, chainClone->countChainElements());
523 EXPECT_THROW(chainClone->gather(4000), std::overflow_error);
525 chainClone->gather(1521);
526 EXPECT_EQ(3, chainClone->countChainElements());
530 EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
536 auto chainCloneCoalesced = chainClone->cloneCoalesced();
537 EXPECT_EQ(1, chainCloneCoalesced->countChainElements());
538 EXPECT_EQ(fullLength, chainCloneCoalesced->computeChainDataLength());
544 chainClone->coalesce();
545 EXPECT_EQ(1, chainClone->countChainElements());
549 EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
554 iob1 = IOBuf::create(1);
556 IOBuf* iob1ptr = iob1.get();
557 iob2 = IOBuf::create(3);
559 iob2ptr = iob2.get();
560 iob3 = IOBuf::create(5);
562 iob3ptr = iob3.get();
563 iob4 = IOBuf::create(7);
565 iob4ptr = iob4.get();
567 iob1->prev()->appendChain(
std::move(iob3));
568 iob1->prev()->appendChain(
std::move(iob4));
569 EXPECT_EQ(4, iob1->countChainElements());
570 EXPECT_EQ(16, iob1->computeChainDataLength());
575 EXPECT_EQ(3, iob1->countChainElements());
576 EXPECT_EQ(11, iob1->computeChainDataLength());
581 EXPECT_EQ(2, iob1->countChainElements());
583 EXPECT_EQ(4, iob1->computeChainDataLength());
588 EXPECT_EQ(1, iob1->countChainElements());
589 EXPECT_EQ(1, iob1->computeChainDataLength());
591 EXPECT_EQ(1, iob2->countChainElements());
592 EXPECT_EQ(3, iob2->computeChainDataLength());
606 boost::mt19937 gen(fillSeed);
611 unique_ptr<IOBuf> iob(IOBuf::create(2000));
613 const void* p1 = iob->
buffer();
622 unique_ptr<IOBuf> iob(IOBuf::create(2000));
627 const void* p1 = iob->
buffer();
642 unique_ptr<IOBuf> iob(IOBuf::create(2000));
647 const void* p1 = iob->
buffer();
659 unique_ptr<IOBuf> iob(IOBuf::create(0));
668 auto iob = IOBuf::takeOwnership(buf, 100);
669 iob->reserve(0, 2000);
678 auto iob = IOBuf::takeOwnership(buf, 100,
testFreeFn, &freeCount);
679 iob->reserve(0, 2000);
692 std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
699 std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
709 IOBuf stackBuf(IOBuf::COPY_BUFFER, s, 1, 2);
714 reinterpret_cast<const char*>(stackBuf.data()), stackBuf.length()));
720 auto buf = IOBuf::maybeCopyBuffer(s, 1, 2);
724 std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
728 buf = IOBuf::maybeCopyBuffer(
"", 5, 7);
731 buf = IOBuf::maybeCopyBuffer(
"");
742 int customDeleterCount = 0;
743 int destructorCount = 0;
744 struct OwnershipTestClass {
745 explicit OwnershipTestClass(
int v = 0) :
val(
v) {}
746 ~OwnershipTestClass() {
752 typedef std::function<void(OwnershipTestClass*)> CustomDeleter;
754 void customDelete(OwnershipTestClass* p) {
755 ++customDeleterCount;
759 void customDeleteArray(OwnershipTestClass* p) {
760 ++customDeleterCount;
768 { std::unique_ptr<OwnershipTestClass> p(
new OwnershipTestClass()); }
772 { std::unique_ptr<OwnershipTestClass[]> p(
new OwnershipTestClass[2]); }
777 std::unique_ptr<OwnershipTestClass> p(
new OwnershipTestClass());
778 std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(
std::move(p)));
786 std::unique_ptr<OwnershipTestClass[]> p(
new OwnershipTestClass[2]);
787 std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(
std::move(p), 2));
793 customDeleterCount = 0;
796 std::unique_ptr<OwnershipTestClass, CustomDeleter> p(
797 new OwnershipTestClass(), customDelete);
798 std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(
std::move(p)));
805 customDeleterCount = 0;
808 std::unique_ptr<OwnershipTestClass[], CustomDeleter> p(
809 new OwnershipTestClass[2], CustomDeleter(customDeleteArray));
810 std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(
std::move(p), 2));
819 size_t alignment =
alignof(std::max_align_t);
821 std::vector<size_t>
sizes{0, 1, 64, 256, 1024, 1 << 10};
823 auto buf = IOBuf::create(
size);
824 uintptr_t p =
reinterpret_cast<uintptr_t
>(buf->data());
830 auto buf = IOBuf::create(0);
832 const std::size_t n = 10000;
835 for (std::size_t
i = 0;
i < n;
i++) {
836 *typed.writableTail() =
i;
840 for (std::size_t
i = 0;
i < n;
i++) {
853 :
public ::testing::TestWithParam<std::tuple<int, int, bool, BufType>> {
856 elementSize_ = std::get<0>(GetParam());
857 elementCount_ = std::get<1>(GetParam());
858 shared_ = std::get<2>(GetParam());
859 type_ = std::get<3>(GetParam());
862 for (
int i = 0;
i < elementCount_ - 1; ++
i) {
865 EXPECT_EQ(elementCount_, buf_->countChainElements());
866 EXPECT_EQ(elementCount_ * elementSize_, buf_->computeChainDataLength());
868 buf2_ = buf_->clone();
869 EXPECT_EQ(elementCount_, buf2_->countChainElements());
870 EXPECT_EQ(elementCount_ * elementSize_, buf2_->computeChainDataLength());
875 unique_ptr<IOBuf> buf;
878 buf = IOBuf::create(elementSize_);
879 buf->
append(elementSize_);
882 void*
data = malloc(elementSize_);
884 throw std::bad_alloc();
886 buf = IOBuf::takeOwnership(data, elementSize_);
891 buf = IOBuf::takeOwnership(data, elementSize_,
testFreeFn);
895 unique_ptr<uint8_t[]>
data(
new uint8_t[elementSize_]);
896 buf = IOBuf::wrapBuffer(data.get(), elementSize_);
897 ownedBuffers_.emplace_back(
std::move(data));
901 throw std::invalid_argument(
"unexpected buffer type parameter");
907 void check(std::unique_ptr<IOBuf>& buf) {
909 EXPECT_EQ(elementCount_ * elementSize_, str.size());
910 EXPECT_EQ(elementCount_ * elementSize_, strspn(str.c_str(),
"x"));
937 ::testing::Values(0, 1, 24, 256, 1 << 10, 1 << 20),
938 ::testing::Values(1, 2, 10),
948 boost::mt19937 gen(fillSeed);
952 auto buf = IOBuf::create(len + 1);
953 buf->append(rand() % len + 1);
956 for (
size_t i = 0;
i < count - 1;
i++) {
957 auto buf2 = IOBuf::create(len + 1);
958 buf2->append(rand() % len + 1);
962 EXPECT_EQ(count, buf->countChainElements());
964 auto iov = buf->getIov();
967 IOBuf const* p = buf.get();
968 for (
size_t i = 0;
i <
count;
i++, p = p->next()) {
974 buf->next()->clear();
977 EXPECT_EQ(buf->next()->next()->data(), iov[1].iov_base);
983 EXPECT_EQ(buf->next()->next()->data(), iov[0].iov_base);
986 buf->prev()->clear();
992 const char localBuf[] =
"hello";
993 iov.push_back({(
void*)localBuf,
sizeof(localBuf)});
994 iov.push_back({(
void*)localBuf,
sizeof(localBuf)});
995 buf->appendToIov(&iov);
1001 EXPECT_EQ(buf->next()->next()->data(), iov[2].iov_base);
1010 iov.
push_back({(
void*)hello.data(), hello.size()});
1011 iov.
push_back({(
void*)world.data(), world.size()});
1012 auto wrapped = IOBuf::wrapIov(iov.
data(), iov.
size());
1014 IOBuf const* w = wrapped.get();
1017 for (
size_t i = 0;
i < wrapped->countChainElements(); ++
i, w = w->next()) {
1028 for (
size_t i = 0;
i < words.size();
i++) {
1031 auto buf = IOBuf::takeOwnershipIov(iov.
data(), iov.
size());
1034 IOBuf const*
b = buf.get();
1037 for (
size_t i = 0;
i < buf->countChainElements(); ++
i, b = b->next()) {
1038 EXPECT_EQ(words[
i], static_cast<const char*>(iov[i + 1].iov_base));
1046 auto wrapped = IOBuf::wrapIov(iov.
data(), iov.
size());
1048 EXPECT_EQ(wrapped->countChainElements(), 1);
1051 wrapped = IOBuf::wrapIov(
nullptr, 0);
1053 EXPECT_EQ(wrapped->countChainElements(), 1);
1060 char data[] =
"foobar";
1063 const void*
ptr{
nullptr};
1083 EXPECT_EQ(actualCapacity, b2.capacity());
1103 std::unique_ptr<IOBuf>
seq(std::initializer_list<StringPiece> sps) {
1104 auto ret = IOBuf::create(0);
1105 for (
auto sp : sps) {
1119 auto empty = IOBuf::create(0);
1134 auto a = fromStr(
"hello");
1149 auto b = fromStr(
"hello");
1158 auto c = fromStr(
"hellow");
1165 auto d = fromStr(
"world");
1172 auto e = fromStr(
"helloworld");
1173 auto f = fromStr(
"hello");
1174 f->prependChain(fromStr(
"wo"));
1175 f->prependChain(fromStr(
"rld"));
1185 auto n = std::unique_ptr<IOBuf>{};
1186 auto e = IOBuf::create(0);
1187 auto hello1 =
seq({
"hello"});
1188 auto hello2 =
seq({
"hel",
"lo"});
1189 auto hello3 =
seq({
"he",
"ll",
"o"});
1190 auto hellow =
seq({
"hellow"});
1191 auto hellox =
seq({
"hellox"});
1198 EXPECT_EQ(ordering::eq, op(hello1, hello1));
1199 EXPECT_EQ(ordering::eq, op(hello1, hello2));
1200 EXPECT_EQ(ordering::eq, op(hello1, hello3));
1201 EXPECT_EQ(ordering::lt, op(hello1, hellow));
1202 EXPECT_EQ(ordering::gt, op(hellow, hello1));
1203 EXPECT_EQ(ordering::lt, op(hellow, hellox));
1204 EXPECT_EQ(ordering::gt, op(hellox, hellow));
1216 const char data[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit";
1217 constexpr
size_t reservedSize = 24;
1222 buf.
append(
sizeof(data));
1227 size_t tailroom = 8192 - reservedSize -
sizeof(
data);
1235 auto buf = IOBuf::create(4096);
1236 append(buf,
"hello world");
1237 auto buf2 = IOBuf::create(4096);
1238 append(buf2,
" goodbye");
1255 auto p =
reinterpret_cast<const char*
>(copy2.data());
1265 auto newBufCopy = newBuf;
1279 auto buf = IOBuf::create(4096);
1280 append(buf,
"hello world");
1282 auto buf2 = IOBuf::create(4096);
1283 append(buf2,
" goodbye");
1289 auto copy = buf->cloneOneAsValue();
1296 auto copy2 = buf->cloneAsValue();
1309 auto p =
reinterpret_cast<const char*
>(
copy.data());
1318 auto p2 =
reinterpret_cast<const char*
>(copy2.data());
1327 std::unique_ptr<IOBuf> wrap(
const char* str) {
1328 return IOBuf::wrapBuffer(str, strlen(str));
1331 std::unique_ptr<IOBuf>
copy(
const char* str) {
1339 for (
auto&
b : buf) {
1340 result.append(reinterpret_cast<const char*>(
b.data()),
b.size());
1353 Item(
const char* src,
size_t len) :
size(len) {
1354 CHECK_LE(len,
sizeof(
buffer));
1355 memcpy(
buffer, src, len);
1362 auto hello =
"hello";
1363 struct Item it(hello, strlen(hello));
1366 auto freeFn = [](
void* ,
void* userData) {
1367 auto it2 =
static_cast<struct Item*
>(userData);
1371 auto buf1 = IOBuf::takeOwnership(it.buffer, it.size, freeFn, &it);
1375 buf1->markExternallyShared();
1379 auto buf2 = buf1->clone();
1391 auto hello =
"hello";
1392 auto buf1UP = wrap(hello);
1393 auto buf1 = buf1UP.get();
1395 auto buf2UP =
copy(
"world");
1396 auto buf2 = buf2UP.get();
1398 auto buf3UP = wrap(hello);
1399 auto buf3 = buf3UP.get();
1400 auto buf4UP = buf2->clone();
1401 auto buf4 = buf4UP.get();
1424 buf1->makeManaged();
1444 writableStr(*buf1)[0] =
'j';
1445 writableStr(*buf2)[0] =
'x';
1450 auto b1 = IOBuf::takeOwnership(
nullptr, 0);
1451 auto b2 = fromStr(
"hello");
1452 auto b3 = IOBuf::takeOwnership(
nullptr, 0);
1457 auto br = b1->coalesce();
1463 auto b = IOBuf::createChain(1000, 100);
1465 const uint32_t fillSeed = 0x12345678;
1466 boost::mt19937 gen(fillSeed);
1469 std::size_t length =
c->tailroom();
1471 length =
std::min(length,
c->tailroom());
1472 c->append(length--);
1475 }
while (
c !=
b.get());
1477 auto c =
b->cloneCoalescedAsValue();
1482 EXPECT_EQ(
b->computeChainDataLength(),
c.length());
1488 auto b = IOBuf::create(1000);
1491 const uint32_t fillSeed = 0x12345678;
1492 boost::mt19937 gen(fillSeed);
1495 auto c =
b->cloneCoalesced();
#define EXPECT_LE(val1, val2)
std::vector< uint8_t > buffer(kBufferSize+16)
folly::StringPiece toString(StateEnum state)
#define EXPECT_THROW(statement, expected_exception)
TEST_P(MoveToFbStringTest, Simple)
void testFreeFn(void *buffer, void *ptr)
bool usingJEMalloc() noexcept
void checkChain(IOBuf *buf, boost::mt19937 &gen)
#define EXPECT_EQ(val1, val2)
fbstring moveToFbString()
void appendChain(std::unique_ptr< IOBuf > &&iobuf)
constexpr detail::Map< Move > move
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
void advance(std::size_t amount)
const uint8_t * data() const
Gen seq(Value first, Value last)
void reserve(std::size_t minHeadroom, std::size_t minTailroom)
size_t countChainElements() const
#define EXPECT_GE(val1, val2)
std::size_t capacity() const
std::unique_ptr< IOBuf > buf2_
std::size_t tailroom() const
std::vector< std::unique_ptr< uint8_t[]> > ownedBuffers_
uint32_t capacity() const
void push_back(const T &value)
std::unique_ptr< folly::IOBuf > makeBuf(uint32_t size)
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
constexpr auto size(C const &c) -> decltype(c.size())
void prepend(std::unique_ptr< IOBuf > &buf, StringPiece str)
constexpr auto empty(C const &c) -> decltype(c.empty())
void prepend(std::size_t amount)
std::size_t headroom() const
std::size_t length() const
void deleteArrayBuffer(void *buf, void *arg)
INSTANTIATE_TEST_CASE_P(MoveToFbString, MoveToFbStringTest,::testing::Combine(::testing::Values(0, 1, 24, 256, 1<< 10, 1<< 20),::testing::Values(1, 2, 10),::testing::Bool(),::testing::Values(CREATE, TAKE_OWNERSHIP_MALLOC, TAKE_OWNERSHIP_CUSTOM, USER_OWNED)))
std::unique_ptr< IOBuf > cloneOne() const
std::unique_ptr< IOBuf > unlink()
void check(std::unique_ptr< IOBuf > &buf)
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
void prependChain(std::unique_ptr< IOBuf > &&iobuf)
std::size_t computeChainDataLength() const
std::unique_ptr< IOBuf > copyBuffer(const folly::IOBuf &buf)
#define EXPECT_TRUE(condition)
std::unique_ptr< IOBuf > makeBuf()
Range< const unsigned char * > ByteRange
#define EXPECT_NE(val1, val2)
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
#define EXPECT_FALSE(condition)
basic_fbstring< char > fbstring
Range< const char * > StringPiece
size_type size() const noexcept
const uint8_t * buffer() const
#define ASSERT_TRUE(condition)
static constexpr uint64_t data[1]
void reserve(uint32_t minHeadroom, uint32_t minTailroom)
bool check(const dynamic &schema, const dynamic &value, bool check=true)
std::unique_ptr< IOBuf > buf_
void append(std::size_t amount)
void testAllocSize(uint32_t requestedCapacity)