proxygen
IOBufTest.cpp File Reference
#include <folly/io/IOBuf.h>
#include <folly/io/TypedIOBuf.h>
#include <cstddef>
#include <boost/random.hpp>
#include <folly/Range.h>
#include <folly/memory/Malloc.h>
#include <folly/portability/GTest.h>

Go to the source code of this file.

Classes

class  MoveToFbStringTest
 

Enumerations

enum  BufType { CREATE, TAKE_OWNERSHIP_MALLOC, TAKE_OWNERSHIP_CUSTOM, USER_OWNED }
 

Functions

void append (std::unique_ptr< IOBuf > &buf, StringPiece str)
 
void prepend (std::unique_ptr< IOBuf > &buf, StringPiece str)
 
 TEST (IOBuf, Simple)
 
void testAllocSize (uint32_t requestedCapacity)
 
 TEST (IOBuf, AllocSizes)
 
void deleteArrayBuffer (void *buf, void *arg)
 
 TEST (IOBuf, TakeOwnership)
 
 TEST (IOBuf, WrapBuffer)
 
 TEST (IOBuf, CreateCombined)
 
void fillBuf (uint8_t *buf, uint32_t length, boost::mt19937 &gen)
 
void fillBuf (IOBuf *buf, boost::mt19937 &gen)
 
void checkBuf (const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
 
void checkBuf (IOBuf *buf, boost::mt19937 &gen)
 
void checkBuf (ByteRange buf, boost::mt19937 &gen)
 
void checkChain (IOBuf *buf, boost::mt19937 &gen)
 
 TEST (IOBuf, Chaining)
 
void testFreeFn (void *buffer, void *ptr)
 
 TEST (IOBuf, Reserve)
 
 TEST (IOBuf, copyBuffer)
 
 TEST (IOBuf, maybeCopyBuffer)
 
 TEST (IOBuf, copyEmptyBuffer)
 
 TEST (IOBuf, takeOwnershipUniquePtr)
 
 TEST (IOBuf, Alignment)
 
 TEST (TypedIOBuf, Simple)
 
 TEST_P (MoveToFbStringTest, Simple)
 
 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)))
 
 TEST (IOBuf, getIov)
 
 TEST (IOBuf, wrapIov)
 
 TEST (IOBuf, takeOwnershipIov)
 
 TEST (IOBuf, wrapZeroLenIov)
 
 TEST (IOBuf, move)
 
 TEST (IOBuf, HashAndEqual)
 
 TEST (IOBuf, IOBufCompare)
 
 TEST (IOBuf, ReserveWithHeadroom)
 
 TEST (IOBuf, CopyConstructorAndAssignmentOperator)
 
 TEST (IOBuf, CloneAsValue)
 
 TEST (IOBuf, ExternallyShared)
 
 TEST (IOBuf, Managed)
 
 TEST (IOBuf, CoalesceEmptyBuffers)
 
 TEST (IOBuf, CloneCoalescedChain)
 
 TEST (IOBuf, CloneCoalescedSingle)
 

Enumeration Type Documentation

enum BufType
Enumerator
CREATE 
TAKE_OWNERSHIP_MALLOC 
TAKE_OWNERSHIP_CUSTOM 
USER_OWNED 

Definition at line 844 of file IOBufTest.cpp.

Function Documentation

void checkBuf ( const uint8_t buf,
uint32_t  length,
boost::mt19937 &  gen 
)

Definition at line 268 of file IOBufTest.cpp.

References EXPECT_EQ, uint32_t, and uint8_t.

Referenced by checkBuf(), checkChain(), and TEST().

268  {
269  // Rather than using EXPECT_EQ() to check each character,
270  // count the number of differences and the first character that differs.
271  // This way on error we'll report just that information, rather than tons of
272  // failed checks for each byte in the buffer.
273  uint32_t numDifferences = 0;
274  uint32_t firstDiffIndex = 0;
275  uint8_t firstDiffExpected = 0;
276  for (uint32_t n = 0; n < length; ++n) {
277  uint8_t expected = static_cast<uint8_t>(gen() & 0xff);
278  if (buf[n] == expected) {
279  continue;
280  }
281 
282  if (numDifferences == 0) {
283  firstDiffIndex = n;
284  firstDiffExpected = expected;
285  }
286  ++numDifferences;
287  }
288 
289  EXPECT_EQ(0, numDifferences);
290  if (numDifferences > 0) {
291  // Cast to int so it will be printed numerically
292  // rather than as a char if the check fails
293  EXPECT_EQ(
294  static_cast<int>(buf[firstDiffIndex]),
295  static_cast<int>(firstDiffExpected));
296  }
297 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void checkBuf ( IOBuf buf,
boost::mt19937 &  gen 
)

Definition at line 299 of file IOBufTest.cpp.

References checkBuf(), folly::IOBuf::data(), and folly::IOBuf::length().

299  {
300  checkBuf(buf->data(), buf->length(), gen);
301 }
const uint8_t * data() const
Definition: IOBuf.h:499
std::size_t length() const
Definition: IOBuf.h:533
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:268
void checkBuf ( ByteRange  buf,
boost::mt19937 &  gen 
)

Definition at line 303 of file IOBufTest.cpp.

References checkBuf().

303  {
304  checkBuf(buf.data(), buf.size(), gen);
305 }
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:268
void checkChain ( IOBuf buf,
boost::mt19937 &  gen 
)

Definition at line 307 of file IOBufTest.cpp.

References checkBuf(), current, folly::IOBuf::data(), folly::IOBuf::length(), and folly::IOBuf::next().

Referenced by TEST().

307  {
308  IOBuf* current = buf;
309  do {
310  checkBuf(current->data(), current->length(), gen);
311  current = current->next();
312  } while (current != buf);
313 }
const uint8_t * data() const
Definition: IOBuf.h:499
int current
std::size_t length() const
Definition: IOBuf.h:533
IOBuf * next()
Definition: IOBuf.h:600
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:268
void deleteArrayBuffer ( void *  buf,
void *  arg 
)

Definition at line 98 of file IOBufTest.cpp.

References uint32_t, and uint8_t.

Referenced by TEST().

98  {
99  uint32_t* deleteCount = static_cast<uint32_t*>(arg);
100  ++(*deleteCount);
101  uint8_t* bufPtr = static_cast<uint8_t*>(buf);
102  delete[] bufPtr;
103 }
void fillBuf ( uint8_t buf,
uint32_t  length,
boost::mt19937 &  gen 
)

Definition at line 257 of file IOBufTest.cpp.

References uint32_t, and uint8_t.

Referenced by fillBuf(), and TEST().

257  {
258  for (uint32_t n = 0; n < length; ++n) {
259  buf[n] = static_cast<uint8_t>(gen() & 0xff);
260  }
261 }
void fillBuf ( IOBuf buf,
boost::mt19937 &  gen 
)

Definition at line 263 of file IOBufTest.cpp.

References fillBuf(), folly::IOBuf::length(), folly::IOBuf::unshare(), and folly::IOBuf::writableData().

263  {
264  buf->unshare();
265  fillBuf(buf->writableData(), buf->length(), gen);
266 }
void unshare()
Definition: IOBuf.h:997
uint8_t * writableData()
Definition: IOBuf.h:509
std::size_t length() const
Definition: IOBuf.h:533
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:257
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))   
)

Referenced by TEST_P().

void prepend ( std::unique_ptr< IOBuf > &  buf,
StringPiece  str 
)

Definition at line 43 of file IOBufTest.cpp.

References EXPECT_LE, folly::IOBuf::headroom(), folly::IOBuf::prepend(), and folly::IOBuf::writableData().

Referenced by TEST().

43  {
44  EXPECT_LE(str.size(), buf->headroom());
45  memcpy(buf->writableData() - str.size(), str.data(), str.size());
46  buf->prepend(str.size());
47 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
void prepend(std::size_t amount)
Definition: IOBuf.h:673
uint8_t * writableData()
Definition: IOBuf.h:509
std::size_t headroom() const
Definition: IOBuf.h:542
TEST ( IOBuf  ,
Simple   
)

Definition at line 49 of file IOBufTest.cpp.

References folly::IOBuf::advance(), append(), folly::IOBuf::capacity(), folly::IOBuf::clear(), folly::IOBuf::data(), EXPECT_EQ, EXPECT_LE, folly::IOBuf::headroom(), folly::IOBuf::length(), prepend(), string, folly::IOBuf::tailroom(), and uint32_t.

49  {
50  unique_ptr<IOBuf> buf(IOBuf::create(100));
51  uint32_t cap = buf->capacity();
52  EXPECT_LE(100, cap);
53  EXPECT_EQ(0, buf->headroom());
54  EXPECT_EQ(0, buf->length());
55  EXPECT_EQ(cap, buf->tailroom());
56 
57  append(buf, "world");
58  buf->advance(10);
59  EXPECT_EQ(10, buf->headroom());
60  EXPECT_EQ(5, buf->length());
61  EXPECT_EQ(cap - 15, buf->tailroom());
62 
63  prepend(buf, "hello ");
64  EXPECT_EQ(4, buf->headroom());
65  EXPECT_EQ(11, buf->length());
66  EXPECT_EQ(cap - 15, buf->tailroom());
67 
68  const char* p = reinterpret_cast<const char*>(buf->data());
69  EXPECT_EQ("hello world", std::string(p, buf->length()));
70 
71  buf->clear();
72  EXPECT_EQ(0, buf->headroom());
73  EXPECT_EQ(0, buf->length());
74  EXPECT_EQ(cap, buf->tailroom());
75 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
Definition: IOBufTest.cpp:37
void prepend(std::unique_ptr< IOBuf > &buf, StringPiece str)
Definition: IOBufTest.cpp:43
const char * string
Definition: Conv.cpp:212
TEST ( IOBuf  ,
AllocSizes   
)

Definition at line 82 of file IOBufTest.cpp.

References testAllocSize().

82  {
83  // Try with a small allocation size that should fit in the internal buffer
84  testAllocSize(28);
85 
86  // Try with a large allocation size that will require an external buffer.
87  testAllocSize(9000);
88 
89  // 220 bytes is currently the cutoff
90  // (It would be nice to use the IOBuf::kMaxInternalDataSize constant,
91  // but it's private and it doesn't seem worth making it public just for this
92  // test code.)
93  testAllocSize(220);
94  testAllocSize(219);
95  testAllocSize(221);
96 }
void testAllocSize(uint32_t requestedCapacity)
Definition: IOBufTest.cpp:77
TEST ( IOBuf  ,
TakeOwnership   
)

Definition at line 105 of file IOBufTest.cpp.

References folly::IOBuf::buffer(), folly::IOBuf::capacity(), folly::IOBuf::data(), deleteArrayBuffer(), EXPECT_EQ, folly::IOBuf::length(), folly::gen::move, uint32_t, and uint8_t.

105  {
106  uint32_t size1 = 99;
107  uint8_t* buf1 = static_cast<uint8_t*>(malloc(size1));
108  unique_ptr<IOBuf> iobuf1(IOBuf::takeOwnership(buf1, size1));
109  EXPECT_EQ(buf1, iobuf1->data());
110  EXPECT_EQ(size1, iobuf1->length());
111  EXPECT_EQ(buf1, iobuf1->buffer());
112  EXPECT_EQ(size1, iobuf1->capacity());
113 
114  uint32_t deleteCount = 0;
115  uint32_t size2 = 4321;
116  uint8_t* buf2 = new uint8_t[size2];
117  unique_ptr<IOBuf> iobuf2(
118  IOBuf::takeOwnership(buf2, size2, deleteArrayBuffer, &deleteCount));
119  EXPECT_EQ(buf2, iobuf2->data());
120  EXPECT_EQ(size2, iobuf2->length());
121  EXPECT_EQ(buf2, iobuf2->buffer());
122  EXPECT_EQ(size2, iobuf2->capacity());
123  EXPECT_EQ(0, deleteCount);
124  iobuf2.reset();
125  EXPECT_EQ(1, deleteCount);
126 
127  deleteCount = 0;
128  uint32_t size3 = 3456;
129  uint8_t* buf3 = new uint8_t[size3];
130  uint32_t length3 = 48;
131  unique_ptr<IOBuf> iobuf3(IOBuf::takeOwnership(
132  buf3, size3, length3, deleteArrayBuffer, &deleteCount));
133  EXPECT_EQ(buf3, iobuf3->data());
134  EXPECT_EQ(length3, iobuf3->length());
135  EXPECT_EQ(buf3, iobuf3->buffer());
136  EXPECT_EQ(size3, iobuf3->capacity());
137  EXPECT_EQ(0, deleteCount);
138  iobuf3.reset();
139  EXPECT_EQ(1, deleteCount);
140 
141  deleteCount = 0;
142  {
143  uint32_t size4 = 1234;
144  uint8_t* buf4 = new uint8_t[size4];
145  uint32_t length4 = 48;
146  IOBuf iobuf4(
147  IOBuf::TAKE_OWNERSHIP,
148  buf4,
149  size4,
150  length4,
152  &deleteCount);
153  EXPECT_EQ(buf4, iobuf4.data());
154  EXPECT_EQ(length4, iobuf4.length());
155  EXPECT_EQ(buf4, iobuf4.buffer());
156  EXPECT_EQ(size4, iobuf4.capacity());
157 
158  IOBuf iobuf5 = std::move(iobuf4);
159  EXPECT_EQ(buf4, iobuf5.data());
160  EXPECT_EQ(length4, iobuf5.length());
161  EXPECT_EQ(buf4, iobuf5.buffer());
162  EXPECT_EQ(size4, iobuf5.capacity());
163  EXPECT_EQ(0, deleteCount);
164  }
165  EXPECT_EQ(1, deleteCount);
166 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void deleteArrayBuffer(void *buf, void *arg)
Definition: IOBufTest.cpp:98
TEST ( IOBuf  ,
WrapBuffer   
)

Definition at line 168 of file IOBufTest.cpp.

References folly::IOBuf::buffer(), folly::IOBuf::capacity(), folly::IOBuf::data(), EXPECT_EQ, folly::IOBuf::length(), uint32_t, and uint8_t.

168  {
169  const uint32_t size1 = 1234;
170  uint8_t buf1[size1];
171  unique_ptr<IOBuf> iobuf1(IOBuf::wrapBuffer(buf1, size1));
172  EXPECT_EQ(buf1, iobuf1->data());
173  EXPECT_EQ(size1, iobuf1->length());
174  EXPECT_EQ(buf1, iobuf1->buffer());
175  EXPECT_EQ(size1, iobuf1->capacity());
176 
177  uint32_t size2 = 0x1234;
178  unique_ptr<uint8_t[]> buf2(new uint8_t[size2]);
179  unique_ptr<IOBuf> iobuf2(IOBuf::wrapBuffer(buf2.get(), size2));
180  EXPECT_EQ(buf2.get(), iobuf2->data());
181  EXPECT_EQ(size2, iobuf2->length());
182  EXPECT_EQ(buf2.get(), iobuf2->buffer());
183  EXPECT_EQ(size2, iobuf2->capacity());
184 
185  uint32_t size3 = 4321;
186  unique_ptr<uint8_t[]> buf3(new uint8_t[size3]);
187  IOBuf iobuf3(IOBuf::WRAP_BUFFER, buf3.get(), size3);
188  EXPECT_EQ(buf3.get(), iobuf3.data());
189  EXPECT_EQ(size3, iobuf3.length());
190  EXPECT_EQ(buf3.get(), iobuf3.buffer());
191  EXPECT_EQ(size3, iobuf3.capacity());
192 
193  const uint32_t size4 = 2345;
194  unique_ptr<uint8_t[]> buf4(new uint8_t[size4]);
195  IOBuf iobuf4 = IOBuf::wrapBufferAsValue(buf4.get(), size4);
196  EXPECT_EQ(buf4.get(), iobuf4.data());
197  EXPECT_EQ(size4, iobuf4.length());
198  EXPECT_EQ(buf4.get(), iobuf4.buffer());
199  EXPECT_EQ(size4, iobuf4.capacity());
200 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const uint8_t * data() const
Definition: IOBuf.h:499
std::size_t capacity() const
Definition: IOBuf.h:593
std::size_t length() const
Definition: IOBuf.h:533
const uint8_t * buffer() const
Definition: IOBuf.h:562
TEST ( IOBuf  ,
CreateCombined   
)

Definition at line 202 of file IOBufTest.cpp.

References EXPECT_FALSE, and EXPECT_TRUE.

202  {
203  // Create a combined IOBuf, then destroy it.
204  // The data buffer and IOBuf both become unused as part of the destruction
205  {
206  auto buf = IOBuf::createCombined(256);
207  EXPECT_FALSE(buf->isShared());
208  }
209 
210  // Create a combined IOBuf, clone from it, and then destroy the original
211  // IOBuf. The data buffer cannot be deleted until the clone is also
212  // destroyed.
213  {
214  auto bufA = IOBuf::createCombined(256);
215  EXPECT_FALSE(bufA->isShared());
216  auto bufB = bufA->clone();
217  EXPECT_TRUE(bufA->isShared());
218  EXPECT_TRUE(bufB->isShared());
219  bufA.reset();
220  EXPECT_FALSE(bufB->isShared());
221  }
222 
223  // Create a combined IOBuf, then call reserve() to get a larger buffer.
224  // The IOBuf no longer points to the combined data buffer, but the
225  // overall memory segment cannot be deleted until the IOBuf is also
226  // destroyed.
227  {
228  auto buf = IOBuf::createCombined(256);
229  buf->reserve(0, buf->capacity() + 100);
230  }
231 
232  // Create a combined IOBuf, clone from it, then call unshare() on the original
233  // buffer. This creates a situation where bufB is pointing at the combined
234  // buffer associated with bufA, but bufA is now using a different buffer.
235  auto testSwap = [](bool resetAFirst) {
236  auto bufA = IOBuf::createCombined(256);
237  EXPECT_FALSE(bufA->isShared());
238  auto bufB = bufA->clone();
239  EXPECT_TRUE(bufA->isShared());
240  EXPECT_TRUE(bufB->isShared());
241  bufA->unshare();
242  EXPECT_FALSE(bufA->isShared());
243  EXPECT_FALSE(bufB->isShared());
244 
245  if (resetAFirst) {
246  bufA.reset();
247  bufB.reset();
248  } else {
249  bufB.reset();
250  bufA.reset();
251  }
252  };
253  testSwap(true);
254  testSwap(false);
255 }
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
Chaining   
)

Definition at line 315 of file IOBufTest.cpp.

References folly::IOBuf::advance(), folly::IOBuf::append(), folly::IOBuf::appendChain(), checkBuf(), checkChain(), folly::IOBuf::cloneOne(), folly::IOBuf::computeChainDataLength(), count, folly::IOBuf::countChainElements(), deleteArrayBuffer(), EXPECT_EQ, EXPECT_FALSE, EXPECT_THROW, EXPECT_TRUE, fillBuf(), folly::IOBuf::isChained(), folly::IOBuf::isShared(), folly::IOBuf::isSharedOne(), folly::IOBuf::length(), folly::gen::move, folly::IOBuf::next(), folly::IOBuf::prependChain(), folly::IOBuf::prev(), uint32_t, uint8_t, folly::IOBuf::unlink(), folly::IOBuf::unshare(), and folly::IOBuf::unshareOne().

315  {
316  uint32_t fillSeed = 0x12345678;
317  boost::mt19937 gen(fillSeed);
318 
319  // An IOBuf with external storage
320  uint32_t headroom = 123;
321  unique_ptr<IOBuf> iob1(IOBuf::create(2048));
322  iob1->advance(headroom);
323  iob1->append(1500);
324  fillBuf(iob1.get(), gen);
325 
326  // An IOBuf with internal storage
327  unique_ptr<IOBuf> iob2(IOBuf::create(20));
328  iob2->append(20);
329  fillBuf(iob2.get(), gen);
330 
331  // An IOBuf around a buffer it doesn't own
332  uint8_t localbuf[1234];
333  fillBuf(localbuf, 1234, gen);
334  unique_ptr<IOBuf> iob3(IOBuf::wrapBuffer(localbuf, sizeof(localbuf)));
335 
336  // An IOBuf taking ownership of a user-supplied buffer
337  uint32_t heapBufSize = 900;
338  uint8_t* heapBuf = static_cast<uint8_t*>(malloc(heapBufSize));
339  fillBuf(heapBuf, heapBufSize, gen);
340  unique_ptr<IOBuf> iob4(IOBuf::takeOwnership(heapBuf, heapBufSize));
341 
342  // An IOBuf taking ownership of a user-supplied buffer with
343  // a custom free function
344  uint32_t arrayBufSize = 321;
345  uint8_t* arrayBuf = new uint8_t[arrayBufSize];
346  fillBuf(arrayBuf, arrayBufSize, gen);
347  uint32_t arrayBufFreeCount = 0;
348  unique_ptr<IOBuf> iob5(IOBuf::takeOwnership(
349  arrayBuf, arrayBufSize, deleteArrayBuffer, &arrayBufFreeCount));
350 
351  EXPECT_FALSE(iob1->isChained());
352  EXPECT_FALSE(iob2->isChained());
353  EXPECT_FALSE(iob3->isChained());
354  EXPECT_FALSE(iob4->isChained());
355  EXPECT_FALSE(iob5->isChained());
356 
357  EXPECT_FALSE(iob1->isSharedOne());
358  EXPECT_FALSE(iob2->isSharedOne());
359  EXPECT_TRUE(iob3->isSharedOne()); // since we own the buffer
360  EXPECT_FALSE(iob4->isSharedOne());
361  EXPECT_FALSE(iob5->isSharedOne());
362 
363  // Chain the buffers all together
364  // Since we are going to relinquish ownership of iob2-5 to the chain,
365  // store raw pointers to them so we can reference them later.
366  IOBuf* iob2ptr = iob2.get();
367  IOBuf* iob3ptr = iob3.get();
368  IOBuf* iob4ptr = iob4.get();
369  IOBuf* iob5ptr = iob5.get();
370 
371  iob1->prependChain(std::move(iob2));
372  iob1->prependChain(std::move(iob4));
373  iob2ptr->appendChain(std::move(iob3));
374  iob1->prependChain(std::move(iob5));
375 
376  EXPECT_EQ(iob2ptr, iob1->next());
377  EXPECT_EQ(iob3ptr, iob2ptr->next());
378  EXPECT_EQ(iob4ptr, iob3ptr->next());
379  EXPECT_EQ(iob5ptr, iob4ptr->next());
380  EXPECT_EQ(iob1.get(), iob5ptr->next());
381 
382  EXPECT_EQ(iob5ptr, iob1->prev());
383  EXPECT_EQ(iob1.get(), iob2ptr->prev());
384  EXPECT_EQ(iob2ptr, iob3ptr->prev());
385  EXPECT_EQ(iob3ptr, iob4ptr->prev());
386  EXPECT_EQ(iob4ptr, iob5ptr->prev());
387 
388  EXPECT_TRUE(iob1->isChained());
389  EXPECT_TRUE(iob2ptr->isChained());
390  EXPECT_TRUE(iob3ptr->isChained());
391  EXPECT_TRUE(iob4ptr->isChained());
392  EXPECT_TRUE(iob5ptr->isChained());
393 
394  std::size_t fullLength =
395  (iob1->length() + iob2ptr->length() + iob3ptr->length() +
396  iob4ptr->length() + iob5ptr->length());
397  EXPECT_EQ(5, iob1->countChainElements());
398  EXPECT_EQ(fullLength, iob1->computeChainDataLength());
399 
400  // Since iob3 is shared, the entire buffer should report itself as shared
401  EXPECT_TRUE(iob1->isShared());
402  // Unshare just iob3
403  iob3ptr->unshareOne();
404  EXPECT_FALSE(iob3ptr->isSharedOne());
405  // Now everything in the chain should be unshared.
406  // Check on all members of the chain just for good measure
407  EXPECT_FALSE(iob1->isShared());
408  EXPECT_FALSE(iob2ptr->isShared());
409  EXPECT_FALSE(iob3ptr->isShared());
410  EXPECT_FALSE(iob4ptr->isShared());
411  EXPECT_FALSE(iob5ptr->isShared());
412 
413  // Check iteration
414  gen.seed(fillSeed);
415  size_t count = 0;
416  for (auto buf : *iob1) {
417  checkBuf(buf, gen);
418  ++count;
419  }
420  EXPECT_EQ(5, count);
421 
422  // Clone one of the IOBufs in the chain
423  unique_ptr<IOBuf> iob4clone = iob4ptr->cloneOne();
424  gen.seed(fillSeed);
425  checkBuf(iob1.get(), gen);
426  checkBuf(iob2ptr, gen);
427  checkBuf(iob3ptr, gen);
428  checkBuf(iob4clone.get(), gen);
429  checkBuf(iob5ptr, gen);
430 
431  EXPECT_TRUE(iob1->isShared());
432  EXPECT_TRUE(iob2ptr->isShared());
433  EXPECT_TRUE(iob3ptr->isShared());
434  EXPECT_TRUE(iob4ptr->isShared());
435  EXPECT_TRUE(iob5ptr->isShared());
436 
437  EXPECT_FALSE(iob1->isSharedOne());
438  EXPECT_FALSE(iob2ptr->isSharedOne());
439  EXPECT_FALSE(iob3ptr->isSharedOne());
440  EXPECT_TRUE(iob4ptr->isSharedOne());
441  EXPECT_FALSE(iob5ptr->isSharedOne());
442 
443  // Unshare that clone
444  EXPECT_TRUE(iob4clone->isSharedOne());
445  iob4clone->unshare();
446  EXPECT_FALSE(iob4clone->isSharedOne());
447  EXPECT_FALSE(iob4ptr->isSharedOne());
448  EXPECT_FALSE(iob1->isShared());
449  iob4clone.reset();
450 
451  // Create a clone of a different IOBuf
452  EXPECT_FALSE(iob1->isShared());
453  EXPECT_FALSE(iob3ptr->isSharedOne());
454 
455  unique_ptr<IOBuf> iob3clone = iob3ptr->cloneOne();
456  gen.seed(fillSeed);
457  checkBuf(iob1.get(), gen);
458  checkBuf(iob2ptr, gen);
459  checkBuf(iob3clone.get(), gen);
460  checkBuf(iob4ptr, gen);
461  checkBuf(iob5ptr, gen);
462 
463  EXPECT_TRUE(iob1->isShared());
464  EXPECT_TRUE(iob3ptr->isSharedOne());
465  EXPECT_FALSE(iob1->isSharedOne());
466 
467  // Delete the clone and make sure the original is unshared
468  iob3clone.reset();
469  EXPECT_FALSE(iob1->isShared());
470  EXPECT_FALSE(iob3ptr->isSharedOne());
471 
472  // Clone the entire chain
473  unique_ptr<IOBuf> chainClone = iob1->clone();
474  // Verify that the data is correct.
475  EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
476  gen.seed(fillSeed);
477  checkChain(chainClone.get(), gen);
478 
479  // Check that the buffers report sharing correctly
480  EXPECT_TRUE(chainClone->isShared());
481  EXPECT_TRUE(iob1->isShared());
482 
483  EXPECT_TRUE(iob1->isSharedOne());
484  EXPECT_TRUE(iob2ptr->isSharedOne());
485  EXPECT_TRUE(iob3ptr->isSharedOne());
486  EXPECT_TRUE(iob4ptr->isSharedOne());
487  EXPECT_TRUE(iob5ptr->isSharedOne());
488 
489  // Unshare the cloned chain
490  chainClone->unshare();
491  EXPECT_FALSE(chainClone->isShared());
492  EXPECT_FALSE(iob1->isShared());
493 
494  // Make sure the unshared result still has the same data
495  EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
496  gen.seed(fillSeed);
497  checkChain(chainClone.get(), gen);
498 
499  // Destroy this chain
500  chainClone.reset();
501 
502  // Clone a new chain
503  EXPECT_FALSE(iob1->isShared());
504  chainClone = iob1->clone();
505  EXPECT_TRUE(iob1->isShared());
506  EXPECT_TRUE(chainClone->isShared());
507 
508  // Delete the original chain
509  iob1.reset();
510  EXPECT_FALSE(chainClone->isShared());
511 
512  // Coalesce the chain
513  //
514  // Coalescing this chain will create a new buffer and release the last
515  // refcount on the original buffers we created. Also make sure
516  // that arrayBufFreeCount increases to one to indicate that arrayBuf was
517  // freed.
518  EXPECT_EQ(5, chainClone->countChainElements());
519  EXPECT_EQ(0, arrayBufFreeCount);
520 
521  // Buffer lengths: 1500 20 1234 900 321
522  // Attempting to gather more data than available should fail
523  EXPECT_THROW(chainClone->gather(4000), std::overflow_error);
524  // Coalesce the first 3 buffers
525  chainClone->gather(1521);
526  EXPECT_EQ(3, chainClone->countChainElements());
527  EXPECT_EQ(0, arrayBufFreeCount);
528 
529  // Make sure the data is still the same after coalescing
530  EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
531  gen.seed(fillSeed);
532  checkChain(chainClone.get(), gen);
533 
534  // cloneCoalesced
535  {
536  auto chainCloneCoalesced = chainClone->cloneCoalesced();
537  EXPECT_EQ(1, chainCloneCoalesced->countChainElements());
538  EXPECT_EQ(fullLength, chainCloneCoalesced->computeChainDataLength());
539  gen.seed(fillSeed);
540  checkChain(chainCloneCoalesced.get(), gen);
541  }
542 
543  // Coalesce the entire chain
544  chainClone->coalesce();
545  EXPECT_EQ(1, chainClone->countChainElements());
546  EXPECT_EQ(1, arrayBufFreeCount);
547 
548  // Make sure the data is still the same after coalescing
549  EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
550  gen.seed(fillSeed);
551  checkChain(chainClone.get(), gen);
552 
553  // Make a new chain to test the unlink and pop operations
554  iob1 = IOBuf::create(1);
555  iob1->append(1);
556  IOBuf* iob1ptr = iob1.get();
557  iob2 = IOBuf::create(3);
558  iob2->append(3);
559  iob2ptr = iob2.get();
560  iob3 = IOBuf::create(5);
561  iob3->append(5);
562  iob3ptr = iob3.get();
563  iob4 = IOBuf::create(7);
564  iob4->append(7);
565  iob4ptr = iob4.get();
566  iob1->appendChain(std::move(iob2));
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());
571 
572  // Unlink from the middle of the chain
573  iob3 = iob3ptr->unlink();
574  EXPECT_TRUE(iob3.get() == iob3ptr);
575  EXPECT_EQ(3, iob1->countChainElements());
576  EXPECT_EQ(11, iob1->computeChainDataLength());
577 
578  // Unlink from the end of the chain
579  iob4 = iob1->prev()->unlink();
580  EXPECT_TRUE(iob4.get() == iob4ptr);
581  EXPECT_EQ(2, iob1->countChainElements());
582  EXPECT_TRUE(iob1->next() == iob2ptr);
583  EXPECT_EQ(4, iob1->computeChainDataLength());
584 
585  // Pop from the front of the chain
586  iob2 = iob1->pop();
587  EXPECT_TRUE(iob1.get() == iob1ptr);
588  EXPECT_EQ(1, iob1->countChainElements());
589  EXPECT_EQ(1, iob1->computeChainDataLength());
590  EXPECT_TRUE(iob2.get() == iob2ptr);
591  EXPECT_EQ(1, iob2->countChainElements());
592  EXPECT_EQ(3, iob2->computeChainDataLength());
593 }
void unshare()
Definition: IOBuf.h:997
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
void checkChain(IOBuf *buf, boost::mt19937 &gen)
Definition: IOBufTest.cpp:307
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void appendChain(std::unique_ptr< IOBuf > &&iobuf)
Definition: IOBuf.h:827
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool isSharedOne() const
Definition: IOBuf.h:952
bool isChained() const
Definition: IOBuf.h:760
void unshareOne()
Definition: IOBuf.h:1015
std::size_t length() const
Definition: IOBuf.h:533
void deleteArrayBuffer(void *buf, void *arg)
Definition: IOBufTest.cpp:98
std::unique_ptr< IOBuf > cloneOne() const
Definition: IOBuf.cpp:531
std::unique_ptr< IOBuf > unlink()
Definition: IOBuf.h:847
IOBuf * next()
Definition: IOBuf.h:600
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:257
bool isShared() const
Definition: IOBuf.h:902
void prependChain(std::unique_ptr< IOBuf > &&iobuf)
Definition: IOBuf.cpp:509
IOBuf * prev()
Definition: IOBuf.h:610
int * count
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:268
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
Reserve   
)

Definition at line 604 of file IOBufTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::buffer(), checkBuf(), folly::IOBuf::data(), EXPECT_EQ, EXPECT_LE, EXPECT_NE, fillBuf(), folly::IOBuf::headroom(), folly::IOBuf::length(), folly::IOBuf::reserve(), folly::IOBuf::tailroom(), testFreeFn(), uint32_t, uint8_t, and folly::usingJEMalloc().

604  {
605  uint32_t fillSeed = 0x23456789;
606  boost::mt19937 gen(fillSeed);
607 
608  // Reserve does nothing if empty and doesn't have to grow the buffer
609  {
610  gen.seed(fillSeed);
611  unique_ptr<IOBuf> iob(IOBuf::create(2000));
612  EXPECT_EQ(0, iob->headroom());
613  const void* p1 = iob->buffer();
614  iob->reserve(5, 15);
615  EXPECT_LE(5, iob->headroom());
616  EXPECT_EQ(p1, iob->buffer());
617  }
618 
619  // Reserve doesn't reallocate if we have enough total room
620  {
621  gen.seed(fillSeed);
622  unique_ptr<IOBuf> iob(IOBuf::create(2000));
623  iob->append(100);
624  fillBuf(iob.get(), gen);
625  EXPECT_EQ(0, iob->headroom());
626  EXPECT_EQ(100, iob->length());
627  const void* p1 = iob->buffer();
628  const uint8_t* d1 = iob->data();
629  iob->reserve(100, 1800);
630  EXPECT_LE(100, iob->headroom());
631  EXPECT_EQ(p1, iob->buffer());
632  EXPECT_EQ(d1 + 100, iob->data());
633  gen.seed(fillSeed);
634  checkBuf(iob.get(), gen);
635  }
636 
637  // Reserve reallocates if we don't have enough total room.
638  // NOTE that, with jemalloc, we know that this won't reallocate in place
639  // as the size is less than jemallocMinInPlaceExpanadable
640  {
641  gen.seed(fillSeed);
642  unique_ptr<IOBuf> iob(IOBuf::create(2000));
643  iob->append(100);
644  fillBuf(iob.get(), gen);
645  EXPECT_EQ(0, iob->headroom());
646  EXPECT_EQ(100, iob->length());
647  const void* p1 = iob->buffer();
648  iob->reserve(100, 2512); // allocation sizes are multiples of 256
649  EXPECT_LE(100, iob->headroom());
650  if (folly::usingJEMalloc()) {
651  EXPECT_NE(p1, iob->buffer());
652  }
653  gen.seed(fillSeed);
654  checkBuf(iob.get(), gen);
655  }
656 
657  // Test reserve from internal buffer, this used to segfault
658  {
659  unique_ptr<IOBuf> iob(IOBuf::create(0));
660  iob->reserve(0, 2000);
661  EXPECT_EQ(0, iob->headroom());
662  EXPECT_LE(2000, iob->tailroom());
663  }
664 
665  // Test reserving from a user-allocated buffer.
666  {
667  uint8_t* buf = static_cast<uint8_t*>(malloc(100));
668  auto iob = IOBuf::takeOwnership(buf, 100);
669  iob->reserve(0, 2000);
670  EXPECT_EQ(0, iob->headroom());
671  EXPECT_LE(2000, iob->tailroom());
672  }
673 
674  // Test reserving from a user-allocated with a custom free function.
675  {
676  uint32_t freeCount{0};
677  uint8_t* buf = new uint8_t[100];
678  auto iob = IOBuf::takeOwnership(buf, 100, testFreeFn, &freeCount);
679  iob->reserve(0, 2000);
680  EXPECT_EQ(0, iob->headroom());
681  EXPECT_LE(2000, iob->tailroom());
682  EXPECT_EQ(1, freeCount);
683  }
684 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
void testFreeFn(void *buffer, void *ptr)
Definition: IOBufTest.cpp:595
bool usingJEMalloc() noexcept
Definition: Malloc.h:147
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:257
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:268
TEST ( IOBuf  ,
copyBuffer   
)

Definition at line 686 of file IOBufTest.cpp.

References fizz::test::copyBuffer(), folly::empty(), EXPECT_EQ, EXPECT_LE, s, and string.

686  {
687  std::string s("hello");
688  auto buf = IOBuf::copyBuffer(s.data(), s.size(), 1, 2);
689  EXPECT_EQ(1, buf->headroom());
690  EXPECT_EQ(
691  s,
692  std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
693  EXPECT_LE(2, buf->tailroom());
694 
695  buf = IOBuf::copyBuffer(s, 5, 7);
696  EXPECT_EQ(5, buf->headroom());
697  EXPECT_EQ(
698  s,
699  std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
700  EXPECT_LE(7, buf->tailroom());
701 
703  buf = IOBuf::copyBuffer(empty, 3, 6);
704  EXPECT_EQ(3, buf->headroom());
705  EXPECT_EQ(0, buf->length());
706  EXPECT_LE(6, buf->tailroom());
707 
708  // A stack-allocated version
709  IOBuf stackBuf(IOBuf::COPY_BUFFER, s, 1, 2);
710  EXPECT_EQ(1, stackBuf.headroom());
711  EXPECT_EQ(
712  s,
713  std::string(
714  reinterpret_cast<const char*>(stackBuf.data()), stackBuf.length()));
715  EXPECT_LE(2, stackBuf.tailroom());
716 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
std::unique_ptr< IOBuf > copyBuffer(const folly::IOBuf &buf)
const char * string
Definition: Conv.cpp:212
static set< string > s
TEST ( IOBuf  ,
maybeCopyBuffer   
)

Definition at line 718 of file IOBufTest.cpp.

References folly::empty(), EXPECT_EQ, EXPECT_LE, s, and string.

718  {
719  std::string s("this is a test");
720  auto buf = IOBuf::maybeCopyBuffer(s, 1, 2);
721  EXPECT_EQ(1, buf->headroom());
722  EXPECT_EQ(
723  s,
724  std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
725  EXPECT_LE(2, buf->tailroom());
726 
728  buf = IOBuf::maybeCopyBuffer("", 5, 7);
729  EXPECT_EQ(nullptr, buf.get());
730 
731  buf = IOBuf::maybeCopyBuffer("");
732  EXPECT_EQ(nullptr, buf.get());
733 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
const char * string
Definition: Conv.cpp:212
static set< string > s
TEST ( IOBuf  ,
copyEmptyBuffer   
)

Definition at line 735 of file IOBufTest.cpp.

References fizz::test::copyBuffer(), EXPECT_EQ, and val.

735  {
736  auto buf = IOBuf::copyBuffer(nullptr, 0);
737  EXPECT_EQ(buf->length(), 0);
738 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::unique_ptr< IOBuf > copyBuffer(const folly::IOBuf &buf)
TEST ( IOBuf  ,
takeOwnershipUniquePtr   
)

Definition at line 766 of file IOBufTest.cpp.

References EXPECT_EQ, folly::IOBuf::length(), and folly::gen::move.

766  {
767  destructorCount = 0;
768  { std::unique_ptr<OwnershipTestClass> p(new OwnershipTestClass()); }
769  EXPECT_EQ(1, destructorCount);
770 
771  destructorCount = 0;
772  { std::unique_ptr<OwnershipTestClass[]> p(new OwnershipTestClass[2]); }
773  EXPECT_EQ(2, destructorCount);
774 
775  destructorCount = 0;
776  {
777  std::unique_ptr<OwnershipTestClass> p(new OwnershipTestClass());
778  std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p)));
779  EXPECT_EQ(sizeof(OwnershipTestClass), buf->length());
780  EXPECT_EQ(0, destructorCount);
781  }
782  EXPECT_EQ(1, destructorCount);
783 
784  destructorCount = 0;
785  {
786  std::unique_ptr<OwnershipTestClass[]> p(new OwnershipTestClass[2]);
787  std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p), 2));
788  EXPECT_EQ(2 * sizeof(OwnershipTestClass), buf->length());
789  EXPECT_EQ(0, destructorCount);
790  }
791  EXPECT_EQ(2, destructorCount);
792 
793  customDeleterCount = 0;
794  destructorCount = 0;
795  {
796  std::unique_ptr<OwnershipTestClass, CustomDeleter> p(
797  new OwnershipTestClass(), customDelete);
798  std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p)));
799  EXPECT_EQ(sizeof(OwnershipTestClass), buf->length());
800  EXPECT_EQ(0, destructorCount);
801  }
802  EXPECT_EQ(1, destructorCount);
803  EXPECT_EQ(1, customDeleterCount);
804 
805  customDeleterCount = 0;
806  destructorCount = 0;
807  {
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));
811  EXPECT_EQ(2 * sizeof(OwnershipTestClass), buf->length());
812  EXPECT_EQ(0, destructorCount);
813  }
814  EXPECT_EQ(2, destructorCount);
815  EXPECT_EQ(1, customDeleterCount);
816 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
TEST ( IOBuf  ,
Alignment   
)

Definition at line 818 of file IOBufTest.cpp.

References EXPECT_EQ, folly::size(), and sizes.

818  {
819  size_t alignment = alignof(std::max_align_t);
820 
821  std::vector<size_t> sizes{0, 1, 64, 256, 1024, 1 << 10};
822  for (size_t size : sizes) {
823  auto buf = IOBuf::create(size);
824  uintptr_t p = reinterpret_cast<uintptr_t>(buf->data());
825  EXPECT_EQ(0, p & (alignment - 1)) << "size=" << size;
826  }
827 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
const int sizes[]
TEST ( TypedIOBuf  ,
Simple   
)

Definition at line 829 of file IOBufTest.cpp.

References folly::TypedIOBuf< T >::capacity(), EXPECT_EQ, EXPECT_LE, i, and folly::TypedIOBuf< T >::reserve().

829  {
830  auto buf = IOBuf::create(0);
831  TypedIOBuf<std::size_t> typed(buf.get());
832  const std::size_t n = 10000;
833  typed.reserve(0, n);
834  EXPECT_LE(n, typed.capacity());
835  for (std::size_t i = 0; i < n; i++) {
836  *typed.writableTail() = i;
837  typed.append(1);
838  }
839  EXPECT_EQ(n, typed.length());
840  for (std::size_t i = 0; i < n; i++) {
841  EXPECT_EQ(i, typed.data()[i]);
842  }
843 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
uint32_t capacity() const
Definition: TypedIOBuf.h:96
void reserve(uint32_t minHeadroom, uint32_t minTailroom)
Definition: TypedIOBuf.h:120
TEST ( IOBuf  ,
getIov   
)

Definition at line 946 of file IOBufTest.cpp.

References count, EXPECT_EQ, fillBuf(), i, folly::gen::move, and uint32_t.

946  {
947  uint32_t fillSeed = 0xdeadbeef;
948  boost::mt19937 gen(fillSeed);
949 
950  size_t len = 4096;
951  size_t count = 32;
952  auto buf = IOBuf::create(len + 1);
953  buf->append(rand() % len + 1);
954  fillBuf(buf.get(), gen);
955 
956  for (size_t i = 0; i < count - 1; i++) {
957  auto buf2 = IOBuf::create(len + 1);
958  buf2->append(rand() % len + 1);
959  fillBuf(buf2.get(), gen);
960  buf->prependChain(std::move(buf2));
961  }
962  EXPECT_EQ(count, buf->countChainElements());
963 
964  auto iov = buf->getIov();
965  EXPECT_EQ(count, iov.size());
966 
967  IOBuf const* p = buf.get();
968  for (size_t i = 0; i < count; i++, p = p->next()) {
969  EXPECT_EQ(p->data(), iov[i].iov_base);
970  EXPECT_EQ(p->length(), iov[i].iov_len);
971  }
972 
973  // an empty buf should be skipped in the iov.
974  buf->next()->clear();
975  iov = buf->getIov();
976  EXPECT_EQ(count - 1, iov.size());
977  EXPECT_EQ(buf->next()->next()->data(), iov[1].iov_base);
978 
979  // same for the first one being empty
980  buf->clear();
981  iov = buf->getIov();
982  EXPECT_EQ(count - 2, iov.size());
983  EXPECT_EQ(buf->next()->next()->data(), iov[0].iov_base);
984 
985  // and the last one
986  buf->prev()->clear();
987  iov = buf->getIov();
988  EXPECT_EQ(count - 3, iov.size());
989 
990  // test appending to an existing iovec array
991  iov.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);
996  EXPECT_EQ(count - 1, iov.size());
997  EXPECT_EQ(localBuf, iov[0].iov_base);
998  EXPECT_EQ(localBuf, iov[1].iov_base);
999  // The first two IOBufs were cleared, so the next iov entry
1000  // should be the third IOBuf in the chain.
1001  EXPECT_EQ(buf->next()->next()->data(), iov[2].iov_base);
1002 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:257
int * count
TEST ( IOBuf  ,
wrapIov   
)

Definition at line 1004 of file IOBufTest.cpp.

References folly::fbvector< T, Allocator >::data(), EXPECT_EQ, i, folly::fbvector< T, Allocator >::push_back(), and folly::fbvector< T, Allocator >::size().

1004  {
1005  // Test wrapping IOVs
1006  constexpr folly::StringPiece hello = "hello";
1007  constexpr folly::StringPiece world = "world!";
1009  iov.push_back({nullptr, 0});
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());
1013  EXPECT_EQ(iov.size() - 1, wrapped->countChainElements());
1014  IOBuf const* w = wrapped.get();
1015  // skip the first iovec, which is empty/null, as it is ignored by
1016  // IOBuf::wrapIov
1017  for (size_t i = 0; i < wrapped->countChainElements(); ++i, w = w->next()) {
1018  EXPECT_EQ(w->data(), iov[i + 1].iov_base);
1019  EXPECT_EQ(w->length(), iov[i + 1].iov_len);
1020  }
1021 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
T * data() noexcept
Definition: FBVector.h:1135
void push_back(const T &value)
Definition: FBVector.h:1156
size_type size() const noexcept
Definition: FBVector.h:964
TEST ( IOBuf  ,
takeOwnershipIov   
)

Definition at line 1023 of file IOBufTest.cpp.

References b, data, folly::fbvector< T, Allocator >::data(), EXPECT_EQ, i, folly::fbvector< T, Allocator >::push_back(), and folly::fbvector< T, Allocator >::size().

1023  {
1024  // Test taking IOVs ownership
1025  folly::fbvector<folly::StringPiece> words{"hello", "world!"};
1027  iov.push_back({nullptr, 0});
1028  for (size_t i = 0; i < words.size(); i++) {
1029  iov.push_back({(void*)strdup(words[i].data()), words[i].size() + 1});
1030  }
1031  auto buf = IOBuf::takeOwnershipIov(iov.data(), iov.size());
1032  EXPECT_EQ(iov.size() - 1, buf->countChainElements());
1033 
1034  IOBuf const* b = buf.get();
1035  // skip the first iovec, which is empty/null, as it is ignored by
1036  // IOBuf::takeIovOwnership
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));
1039  }
1040 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
T * data() noexcept
Definition: FBVector.h:1135
void push_back(const T &value)
Definition: FBVector.h:1156
size_type size() const noexcept
Definition: FBVector.h:964
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( IOBuf  ,
wrapZeroLenIov   
)

Definition at line 1042 of file IOBufTest.cpp.

References folly::fbvector< T, Allocator >::data(), EXPECT_EQ, EXPECT_NE, folly::fbvector< T, Allocator >::push_back(), and folly::fbvector< T, Allocator >::size().

1042  {
1044  iov.push_back({nullptr, 0});
1045  iov.push_back({nullptr, 0});
1046  auto wrapped = IOBuf::wrapIov(iov.data(), iov.size());
1047  EXPECT_NE(nullptr, wrapped);
1048  EXPECT_EQ(wrapped->countChainElements(), 1);
1049  EXPECT_EQ(wrapped->length(), 0);
1050 
1051  wrapped = IOBuf::wrapIov(nullptr, 0);
1052  EXPECT_NE(nullptr, wrapped);
1053  EXPECT_EQ(wrapped->countChainElements(), 1);
1054  EXPECT_EQ(wrapped->length(), 0);
1055 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
T * data() noexcept
Definition: FBVector.h:1135
void push_back(const T &value)
Definition: FBVector.h:1156
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
size_type size() const noexcept
Definition: FBVector.h:964
TEST ( IOBuf  ,
move   
)

Definition at line 1057 of file IOBufTest.cpp.

References folly::IOBuf::append(), ASSERT_TRUE, folly::IOBuf::capacity(), fizz::test::copyBuffer(), CREATE, data, folly::IOBuf::data(), EXPECT_EQ, EXPECT_FALSE, EXPECT_GE, folly::IOBuf::isShared(), folly::IOBuf::length(), folly::gen::move, ptr, folly::gen::seq(), uint32_t, and folly::IOBuf::writableTail().

1057  {
1058  // Default allocate an IOBuf on the stack
1059  IOBuf outerBuf;
1060  char data[] = "foobar";
1061  uint32_t length = sizeof(data);
1062  uint32_t actualCapacity{0};
1063  const void* ptr{nullptr};
1064 
1065  {
1066  // Create a small IOBuf on the stack.
1067  // Note that IOBufs created on the stack always use an external buffer.
1068  IOBuf b1(IOBuf::CREATE, 10);
1069  actualCapacity = b1.capacity();
1070  EXPECT_GE(actualCapacity, 10);
1071  EXPECT_EQ(0, b1.length());
1072  EXPECT_FALSE(b1.isShared());
1073  ptr = b1.data();
1074  ASSERT_TRUE(ptr != nullptr);
1075  memcpy(b1.writableTail(), data, length);
1076  b1.append(length);
1077  EXPECT_EQ(length, b1.length());
1078 
1079  // Use the move constructor
1080  IOBuf b2(std::move(b1));
1081  EXPECT_EQ(ptr, b2.data());
1082  EXPECT_EQ(length, b2.length());
1083  EXPECT_EQ(actualCapacity, b2.capacity());
1084  EXPECT_FALSE(b2.isShared());
1085 
1086  // Use the move assignment operator
1087  outerBuf = std::move(b2);
1088  // Close scope, destroying b1 and b2
1089  // (which are both be invalid now anyway after moving out of them)
1090  }
1091 
1092  EXPECT_EQ(ptr, outerBuf.data());
1093  EXPECT_EQ(length, outerBuf.length());
1094  EXPECT_EQ(actualCapacity, outerBuf.capacity());
1095  EXPECT_FALSE(outerBuf.isShared());
1096 }
void * ptr
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const uint8_t * data() const
Definition: IOBuf.h:499
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
std::size_t capacity() const
Definition: IOBuf.h:593
std::size_t length() const
Definition: IOBuf.h:533
bool isShared() const
Definition: IOBuf.h:902
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( IOBuf  ,
HashAndEqual   
)

Definition at line 1112 of file IOBufTest.cpp.

References a, b, c, folly::empty(), EXPECT_EQ, EXPECT_FALSE, EXPECT_NE, EXPECT_TRUE, and f.

1112  {
1114  folly::IOBufHash hash;
1115 
1116  EXPECT_TRUE(eq(nullptr, nullptr));
1117  EXPECT_EQ(0, hash(nullptr));
1118 
1119  auto empty = IOBuf::create(0);
1120 
1121  EXPECT_TRUE(eq(*empty, *empty));
1122  EXPECT_TRUE(eq(empty, empty));
1123  EXPECT_TRUE(eq(empty.get(), empty.get()));
1124 
1125  EXPECT_FALSE(eq(nullptr, empty));
1126  EXPECT_FALSE(eq(empty, nullptr));
1127  EXPECT_FALSE(eq(empty.get(), nullptr));
1128 
1129  EXPECT_EQ(hash(*empty), hash(empty));
1130  EXPECT_EQ(hash(*empty), hash(empty.get()));
1131  EXPECT_NE(0, hash(empty));
1132  EXPECT_NE(0, hash(empty.get()));
1133 
1134  auto a = fromStr("hello");
1135 
1136  EXPECT_TRUE(eq(*a, *a));
1137  EXPECT_TRUE(eq(a, a));
1138  EXPECT_TRUE(eq(a.get(), a.get()));
1139 
1140  EXPECT_FALSE(eq(nullptr, a));
1141  EXPECT_FALSE(eq(a, nullptr));
1142  EXPECT_FALSE(eq(a.get(), nullptr));
1143 
1144  EXPECT_EQ(hash(*a), hash(a));
1145  EXPECT_EQ(hash(*a), hash(a.get()));
1146  EXPECT_NE(0, hash(a));
1147  EXPECT_NE(0, hash(a.get()));
1148 
1149  auto b = fromStr("hello");
1150 
1151  EXPECT_TRUE(eq(*a, *b));
1152  EXPECT_TRUE(eq(a, b));
1153  EXPECT_TRUE(eq(a.get(), b.get()));
1154 
1155  EXPECT_EQ(hash(a), hash(b));
1156  EXPECT_EQ(hash(a.get()), hash(b.get()));
1157 
1158  auto c = fromStr("hellow");
1159 
1160  EXPECT_FALSE(eq(a, c));
1161  EXPECT_FALSE(eq(a.get(), c.get()));
1162  EXPECT_NE(hash(a), hash(c));
1163  EXPECT_NE(hash(a.get()), hash(c.get()));
1164 
1165  auto d = fromStr("world");
1166 
1167  EXPECT_FALSE(eq(a, d));
1168  EXPECT_FALSE(eq(a.get(), d.get()));
1169  EXPECT_NE(hash(a), hash(d));
1170  EXPECT_NE(hash(a.get()), hash(d.get()));
1171 
1172  auto e = fromStr("helloworld");
1173  auto f = fromStr("hello");
1174  f->prependChain(fromStr("wo"));
1175  f->prependChain(fromStr("rld"));
1176 
1177  EXPECT_TRUE(eq(e, f));
1178  EXPECT_TRUE(eq(e.get(), f.get()));
1179  EXPECT_EQ(hash(e), hash(f));
1180  EXPECT_EQ(hash(e.get()), hash(f.get()));
1181 }
auto f
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
char a
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
char c
TEST ( IOBuf  ,
IOBufCompare   
)

Definition at line 1183 of file IOBufTest.cpp.

References EXPECT_EQ, and folly::gen::seq().

1183  {
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"});
1192 
1193  EXPECT_EQ(ordering::eq, op(n, n));
1194  EXPECT_EQ(ordering::lt, op(n, e));
1195  EXPECT_EQ(ordering::gt, op(e, n));
1196  EXPECT_EQ(ordering::lt, op(e, hello1));
1197  EXPECT_EQ(ordering::gt, op(hello1, e));
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));
1205 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Gen seq(Value first, Value last)
Definition: Base.h:484
TEST ( IOBuf  ,
ReserveWithHeadroom   
)

Definition at line 1211 of file IOBufTest.cpp.

References folly::IOBuf::advance(), folly::IOBuf::append(), CREATE, data, folly::IOBuf::data(), EXPECT_EQ, EXPECT_LE, folly::IOBuf::length(), folly::IOBuf::reserve(), folly::IOBuf::tailroom(), and folly::IOBuf::writableData().

1211  {
1212  // This is assuming jemalloc, where we know that 4096 and 8192 bytes are
1213  // valid (and consecutive) allocation sizes. We're hoping that our
1214  // 4096-byte buffer can be expanded in place to 8192 (in practice, this
1215  // usually happens).
1216  const char data[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
1217  constexpr size_t reservedSize = 24; // sizeof(SharedInfo)
1218  // chosen carefully so that the buffer is exactly 4096 bytes
1219  IOBuf buf(IOBuf::CREATE, 4096 - reservedSize);
1220  buf.advance(10);
1221  memcpy(buf.writableData(), data, sizeof(data));
1222  buf.append(sizeof(data));
1223  EXPECT_EQ(sizeof(data), buf.length());
1224 
1225  // Grow the buffer (hopefully in place); this would incorrectly reserve
1226  // the 10 bytes of headroom, giving us 10 bytes less than requested.
1227  size_t tailroom = 8192 - reservedSize - sizeof(data);
1228  buf.reserve(0, tailroom);
1229  EXPECT_LE(tailroom, buf.tailroom());
1230  EXPECT_EQ(sizeof(data), buf.length());
1231  EXPECT_EQ(0, memcmp(data, buf.data(), sizeof(data)));
1232 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( IOBuf  ,
CopyConstructorAndAssignmentOperator   
)

Definition at line 1234 of file IOBufTest.cpp.

References append(), folly::copy(), folly::IOBuf::CREATE, EXPECT_EQ, EXPECT_FALSE, EXPECT_NE, EXPECT_TRUE, folly::IOBuf::isShared(), folly::gen::move, and string.

1234  {
1235  auto buf = IOBuf::create(4096);
1236  append(buf, "hello world");
1237  auto buf2 = IOBuf::create(4096);
1238  append(buf2, " goodbye");
1239  buf->prependChain(std::move(buf2));
1240  EXPECT_FALSE(buf->isShared());
1241 
1242  {
1243  auto copy = *buf;
1244  EXPECT_TRUE(buf->isShared());
1245  EXPECT_TRUE(copy.isShared());
1246  EXPECT_EQ((void*)buf->data(), (void*)copy.data());
1247  EXPECT_NE(buf->next(), copy.next()); // actually different buffers
1248 
1249  auto copy2 = *buf;
1250  copy2.coalesce();
1251  EXPECT_TRUE(buf->isShared());
1252  EXPECT_TRUE(copy.isShared());
1253  EXPECT_FALSE(copy2.isShared());
1254 
1255  auto p = reinterpret_cast<const char*>(copy2.data());
1256  EXPECT_EQ("hello world goodbye", std::string(p, copy2.length()));
1257  }
1258 
1259  EXPECT_FALSE(buf->isShared());
1260 
1261  {
1262  folly::IOBuf newBuf(folly::IOBuf::CREATE, 4096);
1263  EXPECT_FALSE(newBuf.isShared());
1264 
1265  auto newBufCopy = newBuf;
1266  EXPECT_TRUE(newBuf.isShared());
1267  EXPECT_TRUE(newBufCopy.isShared());
1268 
1269  newBufCopy = *buf;
1270  EXPECT_TRUE(buf->isShared());
1271  EXPECT_FALSE(newBuf.isShared());
1272  EXPECT_TRUE(newBufCopy.isShared());
1273  }
1274 
1275  EXPECT_FALSE(buf->isShared());
1276 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
Definition: IOBufTest.cpp:37
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
CloneAsValue   
)

Definition at line 1278 of file IOBufTest.cpp.

References append(), b, folly::IOBuf::computeChainDataLength(), folly::copy(), fizz::test::copyBuffer(), EXPECT_EQ, EXPECT_FALSE, EXPECT_NE, EXPECT_TRUE, folly::gen::move, string, fizz::toString(), and folly::IOBuf::writableData().

1278  {
1279  auto buf = IOBuf::create(4096);
1280  append(buf, "hello world");
1281  {
1282  auto buf2 = IOBuf::create(4096);
1283  append(buf2, " goodbye");
1284  buf->prependChain(std::move(buf2));
1285  EXPECT_FALSE(buf->isShared());
1286  }
1287 
1288  {
1289  auto copy = buf->cloneOneAsValue();
1290  EXPECT_TRUE(buf->isShared());
1291  EXPECT_TRUE(copy.isShared());
1292  EXPECT_EQ((void*)buf->data(), (void*)copy.data());
1293  EXPECT_TRUE(buf->isChained());
1294  EXPECT_FALSE(copy.isChained());
1295 
1296  auto copy2 = buf->cloneAsValue();
1297  EXPECT_TRUE(buf->isShared());
1298  EXPECT_TRUE(copy.isShared());
1299  EXPECT_TRUE(copy2.isShared());
1300  EXPECT_TRUE(buf->isChained());
1301  EXPECT_TRUE(copy2.isChained());
1302 
1303  copy.unshareOne();
1304  EXPECT_TRUE(buf->isShared());
1305  EXPECT_FALSE(copy.isShared());
1306  EXPECT_NE((void*)buf->data(), (void*)copy.data());
1307  EXPECT_TRUE(copy2.isShared());
1308 
1309  auto p = reinterpret_cast<const char*>(copy.data());
1310  EXPECT_EQ("hello world", std::string(p, copy.length()));
1311 
1312  copy2.coalesce();
1313  EXPECT_FALSE(buf->isShared());
1314  EXPECT_FALSE(copy.isShared());
1315  EXPECT_FALSE(copy2.isShared());
1316  EXPECT_FALSE(copy2.isChained());
1317 
1318  auto p2 = reinterpret_cast<const char*>(copy2.data());
1319  EXPECT_EQ("hello world goodbye", std::string(p2, copy2.length()));
1320  }
1321 
1322  EXPECT_FALSE(buf->isShared());
1323 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
Definition: IOBufTest.cpp:37
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
ExternallyShared   
)

Definition at line 1351 of file IOBufTest.cpp.

References buffer(), EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, folly::size(), uint32_t, and uint8_t.

1351  {
1352  struct Item {
1353  Item(const char* src, size_t len) : size(len) {
1354  CHECK_LE(len, sizeof(buffer));
1355  memcpy(buffer, src, len);
1356  }
1357  uint32_t refcount{0};
1358  uint8_t size;
1359  char buffer[256];
1360  };
1361 
1362  auto hello = "hello";
1363  struct Item it(hello, strlen(hello));
1364 
1365  {
1366  auto freeFn = [](void* /* unused */, void* userData) {
1367  auto it2 = static_cast<struct Item*>(userData);
1368  it2->refcount--;
1369  };
1370  it.refcount++;
1371  auto buf1 = IOBuf::takeOwnership(it.buffer, it.size, freeFn, &it);
1372  EXPECT_TRUE(buf1->isManagedOne());
1373  EXPECT_FALSE(buf1->isSharedOne());
1374 
1375  buf1->markExternallyShared();
1376  EXPECT_TRUE(buf1->isSharedOne());
1377 
1378  {
1379  auto buf2 = buf1->clone();
1380  EXPECT_TRUE(buf2->isManagedOne());
1381  EXPECT_TRUE(buf2->isSharedOne());
1382  EXPECT_EQ(buf1->data(), buf2->data());
1383  EXPECT_EQ(it.refcount, 1);
1384  }
1385  EXPECT_EQ(it.refcount, 1);
1386  }
1387  EXPECT_EQ(it.refcount, 0);
1388 }
std::vector< uint8_t > buffer(kBufferSize+16)
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
Managed   
)

Definition at line 1390 of file IOBufTest.cpp.

References folly::copy(), EXPECT_EQ, EXPECT_FALSE, EXPECT_NE, EXPECT_TRUE, folly::gen::move, and fizz::toString().

1390  {
1391  auto hello = "hello";
1392  auto buf1UP = wrap(hello);
1393  auto buf1 = buf1UP.get();
1394  EXPECT_FALSE(buf1->isManagedOne());
1395  auto buf2UP = copy("world");
1396  auto buf2 = buf2UP.get();
1397  EXPECT_TRUE(buf2->isManagedOne());
1398  auto buf3UP = wrap(hello);
1399  auto buf3 = buf3UP.get();
1400  auto buf4UP = buf2->clone();
1401  auto buf4 = buf4UP.get();
1402 
1403  // buf1 and buf3 share the same memory (but are unmanaged)
1404  EXPECT_FALSE(buf1->isManagedOne());
1405  EXPECT_FALSE(buf3->isManagedOne());
1406  EXPECT_TRUE(buf1->isSharedOne());
1407  EXPECT_TRUE(buf3->isSharedOne());
1408  EXPECT_EQ(buf1->data(), buf3->data());
1409 
1410  // buf2 and buf4 share the same memory (but are managed)
1411  EXPECT_TRUE(buf2->isManagedOne());
1412  EXPECT_TRUE(buf4->isManagedOne());
1413  EXPECT_TRUE(buf2->isSharedOne());
1414  EXPECT_TRUE(buf4->isSharedOne());
1415  EXPECT_EQ(buf2->data(), buf4->data());
1416 
1417  buf1->prependChain(std::move(buf2UP));
1418  buf1->prependChain(std::move(buf3UP));
1419  buf1->prependChain(std::move(buf4UP));
1420 
1421  EXPECT_EQ("helloworldhelloworld", toString(*buf1));
1422  EXPECT_FALSE(buf1->isManaged());
1423 
1424  buf1->makeManaged();
1425  EXPECT_TRUE(buf1->isManaged());
1426 
1427  // buf1 and buf3 are now unshared (because they were unmanaged)
1428  EXPECT_TRUE(buf1->isManagedOne());
1429  EXPECT_TRUE(buf3->isManagedOne());
1430  EXPECT_FALSE(buf1->isSharedOne());
1431  EXPECT_FALSE(buf3->isSharedOne());
1432  EXPECT_NE(buf1->data(), buf3->data());
1433 
1434  // buf2 and buf4 are still shared
1435  EXPECT_TRUE(buf2->isManagedOne());
1436  EXPECT_TRUE(buf4->isManagedOne());
1437  EXPECT_TRUE(buf2->isSharedOne());
1438  EXPECT_TRUE(buf4->isSharedOne());
1439  EXPECT_EQ(buf2->data(), buf4->data());
1440 
1441  // And verify that the truth is what we expect: modify a byte in buf1 and
1442  // buf2, see that the change from buf1 is *not* reflected in buf3, but the
1443  // change from buf2 is reflected in buf4.
1444  writableStr(*buf1)[0] = 'j';
1445  writableStr(*buf2)[0] = 'x';
1446  EXPECT_EQ("jelloxorldhelloxorld", toString(*buf1));
1447 }
folly::StringPiece toString(StateEnum state)
Definition: State.cpp:16
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
CoalesceEmptyBuffers   
)

Definition at line 1449 of file IOBufTest.cpp.

References EXPECT_TRUE, and folly::gen::move.

1449  {
1450  auto b1 = IOBuf::takeOwnership(nullptr, 0);
1451  auto b2 = fromStr("hello");
1452  auto b3 = IOBuf::takeOwnership(nullptr, 0);
1453 
1454  b2->appendChain(std::move(b3));
1455  b1->appendChain(std::move(b2));
1456 
1457  auto br = b1->coalesce();
1458 
1459  EXPECT_TRUE(ByteRange(StringPiece("hello")) == br);
1460 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Range< const unsigned char * > ByteRange
Definition: Range.h:1163
Range< const char * > StringPiece
TEST ( IOBuf  ,
CloneCoalescedChain   
)

Definition at line 1462 of file IOBufTest.cpp.

References b, c, checkBuf(), EXPECT_EQ, EXPECT_FALSE, EXPECT_LE, fillBuf(), min, and uint32_t.

1462  {
1463  auto b = IOBuf::createChain(1000, 100);
1464  b->advance(10);
1465  const uint32_t fillSeed = 0x12345678;
1466  boost::mt19937 gen(fillSeed);
1467  {
1468  auto c = b.get();
1469  std::size_t length = c->tailroom();
1470  do {
1471  length = std::min(length, c->tailroom());
1472  c->append(length--);
1473  fillBuf(c, gen);
1474  c = c->next();
1475  } while (c != b.get());
1476  }
1477  auto c = b->cloneCoalescedAsValue();
1478  EXPECT_FALSE(c.isChained()); // Not chained
1479  EXPECT_FALSE(c.isSharedOne()); // Not shared
1480  EXPECT_EQ(b->headroom(), c.headroom()); // Preserves headroom
1481  EXPECT_LE(b->prev()->tailroom(), c.tailroom()); // Preserves minimum tailroom
1482  EXPECT_EQ(b->computeChainDataLength(), c.length()); // Same length
1483  gen.seed(fillSeed);
1484  checkBuf(&c, gen); // Same contents
1485 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
LogLevel min
Definition: LogLevel.cpp:30
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:257
void checkBuf(const uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:268
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
char c
TEST ( IOBuf  ,
CloneCoalescedSingle   
)

Definition at line 1487 of file IOBufTest.cpp.

References b, c, EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, fillBuf(), and uint32_t.

1487  {
1488  auto b = IOBuf::create(1000);
1489  b->advance(10);
1490  b->append(900);
1491  const uint32_t fillSeed = 0x12345678;
1492  boost::mt19937 gen(fillSeed);
1493  fillBuf(b.get(), gen);
1494 
1495  auto c = b->cloneCoalesced();
1496  EXPECT_FALSE(c->isChained()); // Not chained
1497  EXPECT_TRUE(c->isSharedOne()); // Shared
1498  EXPECT_EQ(b->buffer(), c->buffer());
1499  EXPECT_EQ(b->capacity(), c->capacity());
1500  EXPECT_EQ(b->data(), c->data());
1501  EXPECT_EQ(b->length(), c->length());
1502 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void fillBuf(uint8_t *buf, uint32_t length, boost::mt19937 &gen)
Definition: IOBufTest.cpp:257
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
char c
TEST_P ( MoveToFbStringTest  ,
Simple   
)

Definition at line 926 of file IOBufTest.cpp.

References check(), CREATE, INSTANTIATE_TEST_CASE_P(), TAKE_OWNERSHIP_CUSTOM, TAKE_OWNERSHIP_MALLOC, and USER_OWNED.

926  {
927  check(buf_);
928  if (shared_) {
929  check(buf2_);
930  }
931 }
bool check(const dynamic &schema, const dynamic &value, bool check=true)
void testAllocSize ( uint32_t  requestedCapacity)

Definition at line 77 of file IOBufTest.cpp.

References folly::IOBuf::capacity(), and EXPECT_GE.

Referenced by TEST().

77  {
78  unique_ptr<IOBuf> iobuf(IOBuf::create(requestedCapacity));
79  EXPECT_GE(iobuf->capacity(), requestedCapacity);
80 }
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
void testFreeFn ( void *  buffer,
void *  ptr 
)

Definition at line 595 of file IOBufTest.cpp.

References buffer(), ptr, uint32_t, and uint8_t.

Referenced by MoveToFbStringTest::makeBuf(), and TEST().

595  {
596  uint32_t* freeCount = static_cast<uint32_t*>(ptr);
597  ;
598  delete[] static_cast<uint8_t*>(buffer);
599  if (freeCount) {
600  ++(*freeCount);
601  }
602 }
void * ptr
std::vector< uint8_t > buffer(kBufferSize+16)