proxygen
IOBufCursorTest.cpp File Reference
#include <folly/io/IOBuf.h>
#include <folly/Format.h>
#include <folly/Range.h>
#include <folly/io/Cursor.h>
#include <folly/portability/GTest.h>
#include <numeric>
#include <vector>

Go to the source code of this file.

Functions

 TEST (IOBuf, RWCursor)
 
 TEST (IOBuf, skip)
 
 TEST (IOBuf, reset)
 
 TEST (IOBuf, copy_assign_convert)
 
 TEST (IOBuf, arithmetic)
 
 TEST (IOBuf, endian)
 
 TEST (IOBuf, Cursor)
 
 TEST (IOBuf, UnshareCursor)
 
 TEST (IOBuf, PullAndPeek)
 
 TEST (IOBuf, pushCursorData)
 
 TEST (IOBuf, Gather)
 
 TEST (IOBuf, cloneAndInsert)
 
 TEST (IOBuf, cloneWithEmptyBufAtStart)
 
 TEST (IOBuf, Appender)
 
 TEST (IOBuf, Printf)
 
 TEST (IOBuf, Format)
 
 TEST (IOBuf, QueueAppender)
 
 TEST (IOBuf, QueueAppenderPushAtMostFillBuffer)
 
 TEST (IOBuf, QueueAppenderInsertOwn)
 
 TEST (IOBuf, QueueAppenderInsertClone)
 
 TEST (IOBuf, CursorOperators)
 
 TEST (IOBuf, StringOperations)
 
 TEST (IOBuf, ReadWhileTrue)
 
 TEST (IOBuf, TestAdvanceToEndSingle)
 
 TEST (IOBuf, TestAdvanceToEndMulti)
 
 TEST (IOBuf, TestRetreatSingle)
 
 TEST (IOBuf, TestRetreatMulti)
 
 TEST (IOBuf, TestRetreatOperators)
 
 TEST (IOBuf, tryRead)
 
 TEST (IOBuf, tryReadLE)
 
 TEST (IOBuf, tryReadBE)
 
 TEST (IOBuf, tryReadConsumesAllInputOnFailure)
 
 TEST (IOBuf, readConsumesAllInputOnFailure)
 
 TEST (IOBuf, pushEmptyByteRange)
 
 TEST (IOBuf, positionTracking)
 

Function Documentation

TEST ( IOBuf  ,
RWCursor   
)

Definition at line 32 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_TRUE, folly::IOBuf::isChained(), folly::gen::move, folly::IOBuf::prependChain(), uint32_t, uint64_t, and uint8_t.

32  {
33  unique_ptr<IOBuf> iobuf1(IOBuf::create(20));
34  iobuf1->append(20);
35  unique_ptr<IOBuf> iobuf2(IOBuf::create(20));
36  iobuf2->append(20);
37 
38  iobuf2.get();
39  iobuf1->prependChain(std::move(iobuf2));
40 
41  EXPECT_TRUE(iobuf1->isChained());
42 
43  RWPrivateCursor wcursor(iobuf1.get());
44  Cursor rcursor(iobuf1.get());
45  wcursor.writeLE((uint64_t)1);
46  wcursor.writeLE((uint64_t)1);
47  wcursor.writeLE((uint64_t)1);
48  wcursor.write((uint8_t)1);
49 
50  EXPECT_EQ(1u, rcursor.readLE<uint64_t>());
51  rcursor.skip(8);
52  EXPECT_EQ(1u, rcursor.readLE<uint32_t>());
53  rcursor.skip(0);
54  EXPECT_EQ(0u, rcursor.read<uint8_t>());
55  EXPECT_EQ(0u, rcursor.read<uint8_t>());
56  EXPECT_EQ(0u, rcursor.read<uint8_t>());
57  EXPECT_EQ(0u, rcursor.read<uint8_t>());
58  EXPECT_EQ(1u, rcursor.read<uint8_t>());
59 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( IOBuf  ,
skip   
)

Definition at line 61 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, folly::io::detail::CursorBase< Derived, BufType >::skip(), uint8_t, and folly::io::detail::Writable< Derived >::write().

61  {
62  unique_ptr<IOBuf> iobuf1(IOBuf::create(20));
63  iobuf1->append(20);
64  RWPrivateCursor wcursor(iobuf1.get());
65  wcursor.write((uint8_t)1);
66  wcursor.write((uint8_t)2);
67  Cursor cursor(iobuf1.get());
68  cursor.skip(1);
69  EXPECT_EQ(2, cursor.read<uint8_t>());
70 }
std::enable_if< std::is_arithmetic< T >::value >::type write(T value)
Definition: Cursor.h:737
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void skip(size_t len)
Definition: Cursor.h:371
TEST ( IOBuf  ,
reset   
)

Definition at line 72 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, uint8_t, and folly::io::detail::Writable< Derived >::write().

72  {
73  unique_ptr<IOBuf> iobuf1(IOBuf::create(20));
74  iobuf1->append(20);
75  RWPrivateCursor wcursor(iobuf1.get());
76  wcursor.write((uint8_t)1);
77  wcursor.write((uint8_t)2);
78  wcursor.reset(iobuf1.get());
79  EXPECT_EQ(1, wcursor.read<uint8_t>());
80 }
std::enable_if< std::is_arithmetic< T >::value >::type write(T value)
Definition: Cursor.h:737
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
copy_assign_convert   
)

Definition at line 82 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, folly::io::detail::CursorBase< Derived, BufType >::read(), uint8_t, and folly::io::detail::Writable< Derived >::write().

82  {
83  unique_ptr<IOBuf> iobuf1(IOBuf::create(20));
84  iobuf1->append(20);
85  RWPrivateCursor wcursor(iobuf1.get());
86  RWPrivateCursor cursor2(wcursor);
87  RWPrivateCursor cursor3(iobuf1.get());
88 
89  wcursor.write((uint8_t)1);
90  cursor3 = wcursor;
91  wcursor.write((uint8_t)2);
92  Cursor cursor4(wcursor);
93  RWPrivateCursor cursor5(wcursor);
94  wcursor.write((uint8_t)3);
95 
96  EXPECT_EQ(1, cursor2.read<uint8_t>());
97  EXPECT_EQ(2, cursor3.read<uint8_t>());
98  EXPECT_EQ(3, cursor4.read<uint8_t>());
99 }
std::enable_if< std::is_arithmetic< T >::value >::type write(T value)
Definition: Cursor.h:737
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
arithmetic   
)

Definition at line 101 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::CREATE, EXPECT_EQ, EXPECT_NE, folly::io::detail::CursorBase< Derived, BufType >::read(), start, uint8_t, and folly::io::detail::Writable< Derived >::write().

101  {
102  IOBuf iobuf1(IOBuf::CREATE, 20);
103  iobuf1.append(20);
104  RWPrivateCursor wcursor(&iobuf1);
105  wcursor += 1;
106  wcursor.write((uint8_t)1);
107  Cursor cursor(&iobuf1);
108  cursor += 1;
109  EXPECT_EQ(1, cursor.read<uint8_t>());
110 
111  Cursor start(&iobuf1);
112  Cursor cursor2 = start + 9;
113  EXPECT_EQ(7, cursor2 - cursor);
114  EXPECT_NE(cursor, cursor2);
115  cursor += 8;
116  cursor2 = cursor2 + 1;
117  EXPECT_EQ(cursor, cursor2);
118 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
auto start
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
TEST ( IOBuf  ,
endian   
)

Definition at line 120 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, int16_t, and uint16_t.

120  {
121  unique_ptr<IOBuf> iobuf1(IOBuf::create(20));
122  iobuf1->append(20);
123  RWPrivateCursor wcursor(iobuf1.get());
124  Cursor rcursor(iobuf1.get());
125  uint16_t v = 1;
126  int16_t vu = -1;
127  wcursor.writeBE(v);
128  wcursor.writeBE(vu);
129  // Try a couple combinations to ensure they were generated correctly
130  wcursor.writeBE(vu);
131  wcursor.writeLE(vu);
132  wcursor.writeLE(vu);
133  wcursor.writeLE(v);
134  EXPECT_EQ(v, rcursor.readBE<uint16_t>());
135 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
Cursor   
)

Definition at line 137 of file IOBufCursorTest.cpp.

References ADD_FAILURE, folly::IOBuf::append(), c, folly::IOBuf::create(), and uint8_t.

137  {
138  unique_ptr<IOBuf> iobuf1(IOBuf::create(1));
139  iobuf1->append(1);
140  RWPrivateCursor c(iobuf1.get());
141  c.write((uint8_t)40); // OK
142  try {
143  c.write((uint8_t)10); // Bad write, checked should except.
144  ADD_FAILURE();
145  } catch (...) {
146  }
147 }
#define ADD_FAILURE()
Definition: gtest.h:1808
char c
TEST ( IOBuf  ,
UnshareCursor   
)

Definition at line 149 of file IOBufCursorTest.cpp.

References append(), folly::IOBuf::append(), b, folly::data(), folly::Range< Iter >::data(), folly::empty(), EXPECT_EQ, EXPECT_LE, folly::io::detail::CursorBase< Derived, BufType >::peekBytes(), folly::io::detail::Writable< Derived >::push(), folly::Range< Iter >::size(), folly::io::detail::CursorBase< Derived, BufType >::skip(), string, folly::pushmi::detail::t, folly::IOBuf::tailroom(), fizz::toString(), uint8_t, folly::IOBuf::wrapBuffer(), folly::IOBuf::writableData(), and folly::io::detail::Writable< Derived >::write().

149  {
150  uint8_t buf = 0;
151  unique_ptr<IOBuf> iobuf1(IOBuf::wrapBuffer(&buf, 1));
152  unique_ptr<IOBuf> iobuf2(IOBuf::wrapBuffer(&buf, 1));
153  RWUnshareCursor c1(iobuf1.get());
154  RWUnshareCursor c2(iobuf2.get());
155 
156  c1.write((uint8_t)10); // This should duplicate the two buffers.
157  uint8_t t = c2.read<uint8_t>();
158  EXPECT_EQ(0, t);
159 
160  iobuf1 = IOBuf::wrapBuffer(&buf, 1);
161  iobuf2 = IOBuf::wrapBuffer(&buf, 1);
162  RWPrivateCursor c3(iobuf1.get());
163  RWPrivateCursor c4(iobuf2.get());
164 
165  c3.write((uint8_t)10); // This should _not_ duplicate the two buffers.
166  t = c4.read<uint8_t>();
167  EXPECT_EQ(10, t);
168 }
std::enable_if< std::is_arithmetic< T >::value >::type write(T value)
Definition: Cursor.h:737
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
PullAndPeek   
)

Definition at line 194 of file IOBufCursorTest.cpp.

References append(), b, folly::IOBuf::computeChainDataLength(), folly::IOBuf::countChainElements(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_THROW, folly::io::RWCursor< access >::gather(), folly::gen::move, folly::IOBuf::prependChain(), and string.

194  {
195  std::unique_ptr<IOBuf> iobuf1(IOBuf::create(10));
196  append(iobuf1, "he");
197  std::unique_ptr<IOBuf> iobuf2(IOBuf::create(10));
198  append(iobuf2, "llo ");
199  std::unique_ptr<IOBuf> iobuf3(IOBuf::create(10));
200  append(iobuf3, "world");
201  iobuf1->prependChain(std::move(iobuf2));
202  iobuf1->prependChain(std::move(iobuf3));
203  EXPECT_EQ(3, iobuf1->countChainElements());
204  EXPECT_EQ(11, iobuf1->computeChainDataLength());
205 
206  char buf[12];
207  memset(buf, 0, sizeof(buf));
208  Cursor(iobuf1.get()).pull(buf, 11);
209  EXPECT_EQ("hello world", std::string(buf));
210 
211  memset(buf, 0, sizeof(buf));
212  EXPECT_EQ(11, Cursor(iobuf1.get()).pullAtMost(buf, 20));
213  EXPECT_EQ("hello world", std::string(buf));
214 
215  EXPECT_THROW({ Cursor(iobuf1.get()).pull(buf, 20); }, std::out_of_range);
216 
217  {
218  RWPrivateCursor cursor(iobuf1.get());
219  auto b = cursor.peekBytes();
220  EXPECT_EQ("he", StringPiece(b));
221  cursor.skip(b.size());
222  b = cursor.peekBytes();
223  EXPECT_EQ("llo ", StringPiece(b));
224  cursor.skip(b.size());
225  b = cursor.peekBytes();
226  EXPECT_EQ("world", StringPiece(b));
227  cursor.skip(b.size());
228  EXPECT_EQ(3, iobuf1->countChainElements());
229  EXPECT_EQ(11, iobuf1->computeChainDataLength());
230  }
231 
232  {
233  RWPrivateCursor cursor(iobuf1.get());
234  cursor.gather(11);
235  auto b = cursor.peekBytes();
236  EXPECT_EQ("hello world", StringPiece(b));
237  EXPECT_EQ(1, iobuf1->countChainElements());
238  EXPECT_EQ(11, iobuf1->computeChainDataLength());
239  }
240 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
char b
#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
const char * string
Definition: Conv.cpp:212
Range< const char * > StringPiece
void gather(size_t n)
Definition: Cursor.h:831
TEST ( IOBuf  ,
pushCursorData   
)

Definition at line 242 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_FALSE, EXPECT_THROW, EXPECT_TRUE, folly::IOBuf::isChained(), folly::gen::move, folly::IOBuf::prependChain(), folly::io::detail::Writable< Derived >::push(), folly::IOBuf::trimStart(), uint32_t, and uint64_t.

242  {
243  unique_ptr<IOBuf> iobuf1(IOBuf::create(20));
244  iobuf1->append(15);
245  iobuf1->trimStart(5);
246  unique_ptr<IOBuf> iobuf2(IOBuf::create(10));
247  unique_ptr<IOBuf> iobuf3(IOBuf::create(10));
248  iobuf3->append(10);
249 
250  iobuf1->prependChain(std::move(iobuf2));
251  iobuf1->prependChain(std::move(iobuf3));
252  EXPECT_TRUE(iobuf1->isChained());
253 
254  // write 20 bytes to the buffer chain
255  RWPrivateCursor wcursor(iobuf1.get());
256  EXPECT_FALSE(wcursor.isAtEnd());
257  wcursor.writeBE<uint64_t>(1);
258  wcursor.writeBE<uint64_t>(10);
259  wcursor.writeBE<uint32_t>(20);
260  EXPECT_TRUE(wcursor.isAtEnd());
261 
262  // create a read buffer for the buffer chain
263  Cursor rcursor(iobuf1.get());
264  EXPECT_EQ(1, rcursor.readBE<uint64_t>());
265  EXPECT_EQ(10, rcursor.readBE<uint64_t>());
266  EXPECT_EQ(20, rcursor.readBE<uint32_t>());
267  EXPECT_EQ(0, rcursor.totalLength());
268  rcursor.reset(iobuf1.get());
269  EXPECT_EQ(20, rcursor.totalLength());
270 
271  // create another write buffer
272  unique_ptr<IOBuf> iobuf4(IOBuf::create(30));
273  iobuf4->append(30);
274  RWPrivateCursor wcursor2(iobuf4.get());
275  // write buffer chain data into it, now wcursor2 should only
276  // have 10 bytes writable space
277  wcursor2.push(rcursor, 20);
278  EXPECT_EQ(wcursor2.totalLength(), 10);
279  // write again with not enough space in rcursor
280  EXPECT_THROW(wcursor2.push(rcursor, 20), std::out_of_range);
281 
282  // create a read cursor to check iobuf3 data back
283  Cursor rcursor2(iobuf4.get());
284  EXPECT_EQ(1, rcursor2.readBE<uint64_t>());
285  EXPECT_EQ(10, rcursor2.readBE<uint64_t>());
286  EXPECT_EQ(20, rcursor2.readBE<uint32_t>());
287 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void push(const uint8_t *buf, size_t len)
Definition: Cursor.h:755
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
Gather   
)

Definition at line 289 of file IOBufCursorTest.cpp.

References append(), folly::IOBuf::computeChainDataLength(), folly::IOBuf::countChainElements(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_FALSE, EXPECT_THROW, folly::gen::move, and folly::IOBuf::prependChain().

289  {
290  std::unique_ptr<IOBuf> iobuf1(IOBuf::create(10));
291  append(iobuf1, "he");
292  std::unique_ptr<IOBuf> iobuf2(IOBuf::create(10));
293  append(iobuf2, "llo ");
294  std::unique_ptr<IOBuf> iobuf3(IOBuf::create(10));
295  append(iobuf3, "world");
296  iobuf1->prependChain(std::move(iobuf2));
297  iobuf1->prependChain(std::move(iobuf3));
298  EXPECT_EQ(3, iobuf1->countChainElements());
299  EXPECT_EQ(11, iobuf1->computeChainDataLength());
300 
301  // Attempting to gather() more data than available in the chain should fail.
302  // Try from the very beginning of the chain.
303  RWPrivateCursor cursor(iobuf1.get());
304  EXPECT_THROW(cursor.gather(15), std::overflow_error);
305  // Now try from the middle of the chain
306  cursor += 3;
307  EXPECT_THROW(cursor.gather(10), std::overflow_error);
308 
309  // Calling gatherAtMost() should succeed, however, and just gather
310  // as much as it can
311  cursor.gatherAtMost(10);
312  EXPECT_EQ(8, cursor.length());
313  EXPECT_EQ(8, cursor.totalLength());
314  EXPECT_FALSE(cursor.isAtEnd());
315  EXPECT_EQ(
316  "lo world",
318  reinterpret_cast<const char*>(cursor.data()), cursor.length()));
319  EXPECT_EQ(2, iobuf1->countChainElements());
320  EXPECT_EQ(11, iobuf1->computeChainDataLength());
321 
322  // Now try gather again on the chain head
323  cursor = RWPrivateCursor(iobuf1.get());
324  cursor.gather(5);
325  // Since gather() doesn't split buffers, everything should be collapsed into
326  // a single buffer now.
327  EXPECT_EQ(1, iobuf1->countChainElements());
328  EXPECT_EQ(11, iobuf1->computeChainDataLength());
329  EXPECT_EQ(11, cursor.length());
330  EXPECT_EQ(11, cursor.totalLength());
331 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#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
RWCursor< CursorAccess::PRIVATE > RWPrivateCursor
Definition: Cursor.h:958
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
cloneAndInsert   
)

Definition at line 333 of file IOBufCursorTest.cpp.

References append(), folly::IOBuf::computeChainDataLength(), folly::IOBuf::countChainElements(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_THROW, EXPECT_TRUE, folly::gen::move, folly::IOBuf::prependChain(), and uint8_t.

333  {
334  std::unique_ptr<IOBuf> iobuf1(IOBuf::create(10));
335  append(iobuf1, "he");
336  std::unique_ptr<IOBuf> iobuf2(IOBuf::create(10));
337  append(iobuf2, "llo ");
338  std::unique_ptr<IOBuf> iobuf3(IOBuf::create(10));
339  append(iobuf3, "world");
340  iobuf1->prependChain(std::move(iobuf2));
341  iobuf1->prependChain(std::move(iobuf3));
342  EXPECT_EQ(3, iobuf1->countChainElements());
343  EXPECT_EQ(11, iobuf1->computeChainDataLength());
344 
345  std::unique_ptr<IOBuf> cloned;
346 
347  Cursor(iobuf1.get()).clone(cloned, 3);
348  EXPECT_EQ(2, cloned->countChainElements());
349  EXPECT_EQ(3, cloned->computeChainDataLength());
350 
351  EXPECT_EQ(11, Cursor(iobuf1.get()).cloneAtMost(cloned, 20));
352  EXPECT_EQ(3, cloned->countChainElements());
353  EXPECT_EQ(11, cloned->computeChainDataLength());
354 
355  EXPECT_THROW({ Cursor(iobuf1.get()).clone(cloned, 20); }, std::out_of_range);
356 
357  {
358  // Check that inserting in the middle of an iobuf splits
359  RWPrivateCursor cursor(iobuf1.get());
360  Cursor(iobuf1.get()).clone(cloned, 3);
361  EXPECT_EQ(2, cloned->countChainElements());
362  EXPECT_EQ(3, cloned->computeChainDataLength());
363 
364  cursor.skip(1);
365 
366  cursor.insert(std::move(cloned));
367  cursor.insert(folly::IOBuf::create(0));
368  EXPECT_EQ(4, cursor.getCurrentPosition());
369  EXPECT_EQ(7, iobuf1->countChainElements());
370  EXPECT_EQ(14, iobuf1->computeChainDataLength());
371  // Check that nextBuf got set correctly to the buffer with 1 byte left
372  EXPECT_EQ(1, cursor.peekBytes().size());
373  cursor.read<uint8_t>();
374  }
375 
376  {
377  // Check that inserting at the end doesn't create empty buf
378  RWPrivateCursor cursor(iobuf1.get());
379  Cursor(iobuf1.get()).clone(cloned, 1);
380  EXPECT_EQ(1, cloned->countChainElements());
381  EXPECT_EQ(1, cloned->computeChainDataLength());
382 
383  cursor.skip(1);
384 
385  cursor.insert(std::move(cloned));
386  EXPECT_EQ(2, cursor.getCurrentPosition());
387  EXPECT_EQ(8, iobuf1->countChainElements());
388  EXPECT_EQ(15, iobuf1->computeChainDataLength());
389  // Check that nextBuf got set correctly
390  cursor.read<uint8_t>();
391  }
392  {
393  // Check that inserting at the beginning of a chunk (except first one)
394  // doesn't create empty buf
395  RWPrivateCursor cursor(iobuf1.get());
396  Cursor(iobuf1.get()).clone(cloned, 1);
397  EXPECT_EQ(1, cloned->countChainElements());
398  EXPECT_EQ(1, cloned->computeChainDataLength());
399 
400  cursor.skip(1);
401 
402  cursor.insert(std::move(cloned));
403  EXPECT_EQ(2, cursor.getCurrentPosition());
404  EXPECT_EQ(14, cursor.totalLength());
405  EXPECT_EQ(9, iobuf1->countChainElements());
406  EXPECT_EQ(16, iobuf1->computeChainDataLength());
407  // Check that nextBuf got set correctly
408  cursor.read<uint8_t>();
409  }
410  {
411  // Check that inserting at the beginning of a chain DOES keep an empty
412  // buffer.
413  RWPrivateCursor cursor(iobuf1.get());
414  Cursor(iobuf1.get()).clone(cloned, 1);
415  EXPECT_EQ(1, cloned->countChainElements());
416  EXPECT_EQ(1, cloned->computeChainDataLength());
417 
418  cursor.insert(std::move(cloned));
419  EXPECT_EQ(1, cursor.getCurrentPosition());
420  EXPECT_EQ(16, cursor.totalLength());
421  EXPECT_EQ(11, iobuf1->countChainElements());
422  EXPECT_EQ(17, iobuf1->computeChainDataLength());
423  // Check that nextBuf got set correctly
424  cursor.read<uint8_t>();
425  }
426  {
427  // Check that inserting at the end of the buffer keeps it at the end.
428  RWPrivateCursor cursor(iobuf1.get());
429  Cursor(iobuf1.get()).clone(cloned, 1);
430  EXPECT_EQ(1, cloned->countChainElements());
431  EXPECT_EQ(1, cloned->computeChainDataLength());
432 
433  cursor.advanceToEnd();
434  EXPECT_EQ(17, cursor.getCurrentPosition());
435  cursor.insert(std::move(cloned));
436  EXPECT_EQ(18, cursor.getCurrentPosition());
437  EXPECT_EQ(0, cursor.totalLength());
438  EXPECT_EQ(12, iobuf1->countChainElements());
439  EXPECT_EQ(18, iobuf1->computeChainDataLength());
440  EXPECT_TRUE(cursor.isAtEnd());
441  }
442 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
#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
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( IOBuf  ,
cloneWithEmptyBufAtStart   
)

Definition at line 444 of file IOBufCursorTest.cpp.

References append(), folly::IOBuf::create(), folly::data(), folly::empty(), EXPECT_EQ, EXPECT_TRUE, and string.

444  {
446  auto empty = IOBuf::create(0);
447  auto hel = IOBuf::create(3);
448  append(hel, "hel");
449  auto lo = IOBuf::create(2);
450  append(lo, "lo");
451 
452  auto iobuf = empty->clone();
453  iobuf->prependChain(hel->clone());
454  iobuf->prependChain(lo->clone());
455  iobuf->prependChain(empty->clone());
456  iobuf->prependChain(hel->clone());
457  iobuf->prependChain(lo->clone());
458  iobuf->prependChain(empty->clone());
459  iobuf->prependChain(lo->clone());
460  iobuf->prependChain(hel->clone());
461  iobuf->prependChain(lo->clone());
462  iobuf->prependChain(lo->clone());
463 
464  Cursor cursor(iobuf.get());
465  std::unique_ptr<IOBuf> cloned;
466  char data[3];
467  cursor.pull(&data, 3);
468  cursor.clone(cloned, 2);
469  EXPECT_EQ(1, cloned->countChainElements());
470  EXPECT_EQ(2, cloned->length());
471  EXPECT_TRUE(eq(lo, cloned));
472 
473  cursor.pull(&data, 3);
474  EXPECT_EQ("hel", std::string(data, sizeof(data)));
475 
476  cursor.skip(2);
477  cursor.clone(cloned, 2);
478  EXPECT_TRUE(eq(lo, cloned));
479 
480  std::string hello = cursor.readFixedString(5);
481  cursor.clone(cloned, 2);
482  EXPECT_TRUE(eq(lo, cloned));
483 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
Definition: IOBufTest.cpp:37
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( IOBuf  ,
Appender   
)

Definition at line 485 of file IOBufCursorTest.cpp.

References append(), folly::IOBuf::capacity(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_LE, and fizz::toString().

485  {
486  std::unique_ptr<IOBuf> head(IOBuf::create(10));
487  append(head, "hello");
488 
489  Appender app(head.get(), 10);
490  auto cap = head->capacity();
491  auto len1 = app.length();
492  EXPECT_EQ(cap - 5, len1);
493  app.ensure(len1); // won't grow
494  EXPECT_EQ(len1, app.length());
495  app.ensure(len1 + 1); // will grow
496  EXPECT_LE(len1 + 1, app.length());
497 
498  append(app, " world");
499  EXPECT_EQ("hello world", toString(*head));
500 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
folly::StringPiece toString(StateEnum state)
Definition: State.cpp:16
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
Definition: IOBufTest.cpp:37
size_t length() const
Definition: Cursor.h:978
TEST ( IOBuf  ,
Printf   
)

Definition at line 502 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, folly::IOBuf::data(), EXPECT_EQ, EXPECT_GE, folly::IOBuf::length(), folly::IOBuf::moveToFbString(), folly::IOBuf::prev(), folly::io::Appender::printf(), folly::IOBuf::tail(), folly::IOBuf::tailroom(), and folly::basic_fbstring< E, T, A, Storage >::toStdString().

502  {
503  IOBuf head(IOBuf::CREATE, 24);
504  Appender app(&head, 32);
505 
506  app.printf("%s", "test");
507  EXPECT_EQ(head.length(), 4);
508  EXPECT_EQ(0, memcmp(head.data(), "test\0", 5));
509 
510  app.printf(
511  "%d%s %s%s %#x",
512  32,
513  "this string is",
514  "longer than our original allocation size,",
515  "and will therefore require a new allocation",
516  0x12345678);
517  // The tailroom should start with a nul byte now.
518  EXPECT_GE(head.prev()->tailroom(), 1u);
519  EXPECT_EQ(0, *head.prev()->tail());
520 
521  EXPECT_EQ(
522  "test32this string is longer than our original "
523  "allocation size,and will therefore require a "
524  "new allocation 0x12345678",
525  head.moveToFbString().toStdString());
526 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
TEST ( IOBuf  ,
Format   
)

Definition at line 528 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, folly::IOBuf::data(), EXPECT_EQ, folly::format(), folly::IOBuf::length(), folly::IOBuf::moveToFbString(), and folly::basic_fbstring< E, T, A, Storage >::toStdString().

528  {
529  IOBuf head(IOBuf::CREATE, 24);
530  Appender app(&head, 32);
531 
532  format("{}", "test")(app);
533  EXPECT_EQ(head.length(), 4);
534  EXPECT_EQ(0, memcmp(head.data(), "test", 4));
535 
536  auto fmt = format(
537  "{}{} {}{} {:#x}",
538  32,
539  "this string is",
540  "longer than our original allocation size,",
541  "and will therefore require a new allocation",
542  0x12345678);
543  fmt(app);
544  EXPECT_EQ(
545  "test32this string is longer than our original "
546  "allocation size,and will therefore require a "
547  "new allocation 0x12345678",
548  head.moveToFbString().toStdString());
549 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Formatter< false, Args... > format(StringPiece fmt, Args &&...args)
Definition: Format.h:271
TEST ( IOBuf  ,
QueueAppender   
)

Definition at line 551 of file IOBufCursorTest.cpp.

References folly::IOBuf::countChainElements(), EXPECT_EQ, EXPECT_LE, EXPECT_LT, EXPECT_THROW, folly::IOBufQueue::front(), i, uint32_t, and folly::io::detail::Writable< Derived >::writeBE().

551  {
552  folly::IOBufQueue queue;
553 
554  // Allocate 100 bytes at once, but don't grow past 1024
555  QueueAppender app(&queue, 100);
556  size_t n = 1024 / sizeof(uint32_t);
557  for (uint32_t i = 0; i < n; ++i) {
558  app.writeBE(i);
559  }
560 
561  // There must be a goodMallocSize between 100 and 1024...
562  EXPECT_LT(1u, queue.front()->countChainElements());
563  const IOBuf* buf = queue.front();
564  do {
565  EXPECT_LE(100u, buf->capacity());
566  buf = buf->next();
567  } while (buf != queue.front());
568 
569  Cursor cursor(queue.front());
570  for (uint32_t i = 0; i < n; ++i) {
571  EXPECT_EQ(i, cursor.readBE<uint32_t>());
572  }
573 
574  EXPECT_THROW({ cursor.readBE<uint32_t>(); }, std::out_of_range);
575 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
size_t countChainElements() const
Definition: IOBuf.cpp:493
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
TEST ( IOBuf  ,
QueueAppenderPushAtMostFillBuffer   
)

Definition at line 577 of file IOBufCursorTest.cpp.

References folly::data(), EXPECT_EQ, EXPECT_LE, folly::IOBufQueue::front(), fizz::toString(), and uint8_t.

577  {
578  folly::IOBufQueue queue;
579  // There should be a goodMallocSize between 125 and 1000
580  QueueAppender appender{&queue, 125};
581  std::vector<uint8_t> data;
582  data.resize(1000);
583  std::iota(data.begin(), data.end(), uint8_t(0));
584  // Add 100 byte
585  appender.pushAtMost(data.data(), 100);
586  // Add 900 bytes
587  appender.pushAtMost(data.data() + 100, data.size() - 100);
588  const auto buf = queue.front();
589  // Should fill the current buffer before adding another
590  EXPECT_LE(2, buf->countChainElements());
591  EXPECT_EQ(0, buf->tailroom());
592  EXPECT_LE(125, buf->length());
593  EXPECT_EQ(1000, buf->computeChainDataLength());
594  const StringPiece sp{(const char*)data.data(), data.size()};
595  EXPECT_EQ(sp, toString(*buf));
596 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
folly::StringPiece toString(StateEnum state)
Definition: State.cpp:16
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Range< const char * > StringPiece
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( IOBuf  ,
QueueAppenderInsertOwn   
)

Definition at line 598 of file IOBufCursorTest.cpp.

References folly::IOBuf::countChainElements(), folly::IOBuf::create(), folly::data(), EXPECT_EQ, EXPECT_LE, folly::IOBufQueue::front(), folly::gen::move, folly::range(), folly::IOBuf::tailroom(), and fizz::toString().

598  {
599  auto buf = IOBuf::create(10);
600  folly::IOBufQueue queue;
601  QueueAppender appender{&queue, 128};
602  appender.insert(std::move(buf));
603 
604  std::vector<uint8_t> data;
605  data.resize(256);
606  std::iota(data.begin(), data.end(), 0);
607  appender.pushAtMost(folly::range(data));
608  // Buffer is owned, so we should write to it
609  EXPECT_LE(2, queue.front()->countChainElements());
610  EXPECT_EQ(0, queue.front()->tailroom());
611  const StringPiece sp{(const char*)data.data(), data.size()};
612  EXPECT_EQ(sp, toString(*queue.front()));
613 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
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
size_t countChainElements() const
Definition: IOBuf.cpp:493
std::size_t tailroom() const
Definition: IOBuf.h:551
constexpr Range< Iter > range(Iter first, Iter last)
Definition: Range.h:1114
Range< const char * > StringPiece
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( IOBuf  ,
QueueAppenderInsertClone   
)

Definition at line 615 of file IOBufCursorTest.cpp.

References folly::IOBuf::countChainElements(), folly::IOBuf::CREATE, folly::IOBuf::data(), EXPECT_EQ, EXPECT_LT, folly::IOBufQueue::front(), folly::IOBuf::length(), folly::IOBuf::next(), folly::IOBuf::tailroom(), and uint8_t.

615  {
616  IOBuf buf{IOBuf::CREATE, 100};
617  folly::IOBufQueue queue;
618  QueueAppender appender{&queue, 100};
619  // Buffer is shared, so we create a new buffer to write to
620  appender.insert(buf);
621  uint8_t x = 42;
622  appender.pushAtMost(&x, 1);
623  EXPECT_EQ(2, queue.front()->countChainElements());
624  EXPECT_EQ(0, queue.front()->length());
625  EXPECT_LT(0, queue.front()->tailroom());
626  EXPECT_EQ(1, queue.front()->next()->length());
627  EXPECT_EQ(x, queue.front()->next()->data()[0]);
628 }
Definition: InvokeTest.cpp:58
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const uint8_t * data() const
Definition: IOBuf.h:499
size_t countChainElements() const
Definition: IOBuf.cpp:493
std::size_t tailroom() const
Definition: IOBuf.h:551
std::size_t length() const
Definition: IOBuf.h:533
IOBuf * next()
Definition: IOBuf.h:600
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
TEST ( IOBuf  ,
CursorOperators   
)

Definition at line 630 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::appendChain(), c, folly::IOBuf::clone(), folly::IOBuf::computeChainDataLength(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_FALSE, EXPECT_THROW, EXPECT_TRUE, i, and folly::io::detail::CursorBase< Derived, BufType >::skip().

630  {
631  // Test operators on a single-item chain
632  {
633  std::unique_ptr<IOBuf> chain1(IOBuf::create(20));
634  chain1->append(10);
635 
636  Cursor curs1(chain1.get());
637  EXPECT_EQ(0, curs1 - chain1.get());
638  EXPECT_FALSE(curs1.isAtEnd());
639  curs1.skip(3);
640  EXPECT_EQ(3, curs1 - chain1.get());
641  EXPECT_FALSE(curs1.isAtEnd());
642  curs1.skip(7);
643  EXPECT_EQ(10, curs1 - chain1.get());
644  EXPECT_TRUE(curs1.isAtEnd());
645 
646  Cursor curs2(chain1.get());
647  EXPECT_EQ(0, curs2 - chain1.get());
648  EXPECT_EQ(10, curs1 - curs2);
649  EXPECT_THROW(curs2 - curs1, std::out_of_range);
650  }
651 
652  // Test cross-chain operations
653  {
654  std::unique_ptr<IOBuf> chain1(IOBuf::create(20));
655  chain1->append(10);
656  std::unique_ptr<IOBuf> chain2 = chain1->clone();
657 
658  Cursor curs1(chain1.get());
659  Cursor curs2(chain2.get());
660  EXPECT_THROW(curs1 - curs2, std::out_of_range);
661  EXPECT_THROW(curs1 - chain2.get(), std::out_of_range);
662  }
663 
664  // Test operations on multi-item chains
665  {
666  std::unique_ptr<IOBuf> chain(IOBuf::create(20));
667  chain->append(10);
668  chain->appendChain(chain->clone());
669  EXPECT_EQ(20, chain->computeChainDataLength());
670 
671  Cursor curs1(chain.get());
672  curs1.skip(5);
673  Cursor curs2(chain.get());
674  curs2.skip(3);
675  EXPECT_EQ(2, curs1 - curs2);
676  EXPECT_EQ(5, curs1 - chain.get());
677  EXPECT_THROW(curs2 - curs1, std::out_of_range);
678 
679  curs1.skip(7);
680  EXPECT_EQ(9, curs1 - curs2);
681  EXPECT_EQ(12, curs1 - chain.get());
682  EXPECT_THROW(curs2 - curs1, std::out_of_range);
683 
684  curs2.skip(7);
685  EXPECT_EQ(2, curs1 - curs2);
686  EXPECT_THROW(curs2 - curs1, std::out_of_range);
687  }
688 
689  // Test isAtEnd() with empty buffers at the end of a chain
690  {
691  auto iobuf1 = IOBuf::create(20);
692  iobuf1->append(15);
693  iobuf1->trimStart(5);
694 
695  Cursor c(iobuf1.get());
696  EXPECT_FALSE(c.isAtEnd());
697  c.skip(10);
698  EXPECT_TRUE(c.isAtEnd());
699 
700  iobuf1->prependChain(IOBuf::create(10));
701  iobuf1->prependChain(IOBuf::create(10));
702  EXPECT_TRUE(c.isAtEnd());
703  iobuf1->prev()->append(5);
704  EXPECT_FALSE(c.isAtEnd());
705  c.skip(5);
706  EXPECT_TRUE(c.isAtEnd());
707  }
708 
709  // Test canAdvance with a chain of items
710  {
711  auto chain = IOBuf::create(10);
712  chain->append(10);
713  chain->appendChain(chain->clone());
714  EXPECT_EQ(2, chain->countChainElements());
715  EXPECT_EQ(20, chain->computeChainDataLength());
716 
717  Cursor c(chain.get());
718  for (size_t i = 0; i <= 20; ++i) {
719  EXPECT_TRUE(c.canAdvance(i));
720  }
721  EXPECT_FALSE(c.canAdvance(21));
722  c.skip(10);
723  EXPECT_TRUE(c.canAdvance(10));
724  EXPECT_FALSE(c.canAdvance(11));
725  }
726 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void skip(size_t len)
Definition: Cursor.h:371
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
char c
TEST ( IOBuf  ,
StringOperations   
)

Definition at line 728 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_STREQ, EXPECT_THROW, folly::gen::move, folly::IOBuf::next(), folly::IOBuf::prependChain(), folly::io::detail::Writable< Derived >::push(), and uint8_t.

728  {
729  // Test a single buffer with two null-terminated strings and an extra uint8_t
730  // at the end
731  {
732  std::unique_ptr<IOBuf> chain(IOBuf::create(16));
733  Appender app(chain.get(), 0);
734  app.push(reinterpret_cast<const uint8_t*>("hello\0world\0\x01"), 13);
735 
736  Cursor curs(chain.get());
737  EXPECT_STREQ("hello", curs.readTerminatedString().c_str());
738  EXPECT_STREQ("world", curs.readTerminatedString().c_str());
739  EXPECT_EQ(1, curs.read<uint8_t>());
740  }
741 
742  // Test multiple buffers where the first is empty and the string starts in
743  // the second buffer.
744  {
745  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
746  chain->prependChain(IOBuf::create(12));
747  Appender app(chain.get(), 0);
748  app.push(reinterpret_cast<const uint8_t*>("hello world\0"), 12);
749 
750  Cursor curs(chain.get());
751  EXPECT_STREQ("hello world", curs.readTerminatedString().c_str());
752  }
753 
754  // Test multiple buffers with a single null-terminated string spanning them
755  {
756  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
757  chain->prependChain(IOBuf::create(8));
758  chain->append(8);
759  chain->next()->append(4);
760  RWPrivateCursor rwc(chain.get());
761  rwc.push(reinterpret_cast<const uint8_t*>("hello world\0"), 12);
762 
763  Cursor curs(chain.get());
764  EXPECT_STREQ("hello world", curs.readTerminatedString().c_str());
765  }
766 
767  // Test a reading a null-terminated string that's longer than the maximum
768  // allowable length
769  {
770  std::unique_ptr<IOBuf> chain(IOBuf::create(16));
771  Appender app(chain.get(), 0);
772  app.push(reinterpret_cast<const uint8_t*>("hello world\0"), 12);
773 
774  Cursor curs(chain.get());
775  EXPECT_THROW(curs.readTerminatedString('\0', 5), std::length_error);
776  }
777 
778  // Test reading a null-terminated string from a chain with an empty buffer at
779  // the front
780  {
781  std::unique_ptr<IOBuf> buf(IOBuf::create(8));
782  Appender app(buf.get(), 0);
783  app.push(reinterpret_cast<const uint8_t*>("hello\0"), 6);
784  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
785  chain->prependChain(std::move(buf));
786 
787  Cursor curs(chain.get());
788  EXPECT_STREQ("hello", curs.readTerminatedString().c_str());
789  }
790 
791  // Test reading a null-terminated string from a chain that doesn't contain the
792  // terminator
793  {
794  std::unique_ptr<IOBuf> buf(IOBuf::create(8));
795  Appender app(buf.get(), 0);
796  app.push(reinterpret_cast<const uint8_t*>("hello"), 5);
797  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
798  chain->prependChain(std::move(buf));
799 
800  Cursor curs(chain.get());
801  EXPECT_THROW(curs.readTerminatedString(), std::out_of_range);
802  }
803 
804  // Test reading a null-terminated string past the maximum length
805  {
806  std::unique_ptr<IOBuf> buf(IOBuf::create(8));
807  Appender app(buf.get(), 0);
808  app.push(reinterpret_cast<const uint8_t*>("hello\0"), 6);
809  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
810  chain->prependChain(std::move(buf));
811 
812  Cursor curs(chain.get());
813  EXPECT_THROW(curs.readTerminatedString('\0', 3), std::length_error);
814  }
815 
816  // Test reading a two fixed-length strings from a single buffer with an extra
817  // uint8_t at the end
818  {
819  std::unique_ptr<IOBuf> chain(IOBuf::create(16));
820  Appender app(chain.get(), 0);
821  app.push(reinterpret_cast<const uint8_t*>("helloworld\x01"), 11);
822 
823  Cursor curs(chain.get());
824  EXPECT_STREQ("hello", curs.readFixedString(5).c_str());
825  EXPECT_STREQ("world", curs.readFixedString(5).c_str());
826  EXPECT_EQ(1, curs.read<uint8_t>());
827  }
828 
829  // Test multiple buffers where the first is empty and a fixed-length string
830  // starts in the second buffer.
831  {
832  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
833  chain->prependChain(IOBuf::create(16));
834  Appender app(chain.get(), 0);
835  app.push(reinterpret_cast<const uint8_t*>("hello world"), 11);
836 
837  Cursor curs(chain.get());
838  EXPECT_STREQ("hello world", curs.readFixedString(11).c_str());
839  }
840 
841  // Test multiple buffers with a single fixed-length string spanning them
842  {
843  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
844  chain->prependChain(IOBuf::create(8));
845  chain->append(7);
846  chain->next()->append(4);
847  RWPrivateCursor rwc(chain.get());
848  rwc.push(reinterpret_cast<const uint8_t*>("hello world"), 11);
849 
850  Cursor curs(chain.get());
851  EXPECT_STREQ("hello world", curs.readFixedString(11).c_str());
852  }
853 
854  // Test reading a fixed-length string from a chain with an empty buffer at
855  // the front
856  {
857  std::unique_ptr<IOBuf> buf(IOBuf::create(8));
858  Appender app(buf.get(), 0);
859  app.push(reinterpret_cast<const uint8_t*>("hello"), 5);
860  std::unique_ptr<IOBuf> chain(IOBuf::create(8));
861  chain->prependChain(std::move(buf));
862 
863  Cursor curs(chain.get());
864  EXPECT_STREQ("hello", curs.readFixedString(5).c_str());
865  }
866 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void push(const uint8_t *buf, size_t len)
Definition: Cursor.h:755
#define EXPECT_STREQ(s1, s2)
Definition: gtest.h:1995
TEST ( IOBuf  ,
ReadWhileTrue   
)

Definition at line 868 of file IOBufCursorTest.cpp.

References ch, folly::IOBuf::create(), EXPECT_STREQ, EXPECT_TRUE, folly::gen::move, folly::IOBuf::prependChain(), folly::io::detail::Writable< Derived >::push(), and uint8_t.

868  {
869  auto isAlpha = [](uint8_t ch) {
870  return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
871  };
872  auto isDigit = [](uint8_t ch) { return (ch >= '0' && ch <= '9'); };
873 
874  // Test reading alternating alphabetic and numeric strings
875  {
876  std::unique_ptr<IOBuf> chain(IOBuf::create(32));
877  Appender app(chain.get(), 0);
878  app.push(StringPiece("hello123world456"));
879 
880  Cursor curs(chain.get());
881  EXPECT_STREQ("hello", curs.readWhile(isAlpha).c_str());
882  EXPECT_STREQ("123", curs.readWhile(isDigit).c_str());
883  EXPECT_STREQ("world", curs.readWhile(isAlpha).c_str());
884  EXPECT_STREQ("456", curs.readWhile(isDigit).c_str());
885  EXPECT_TRUE(curs.isAtEnd());
886  }
887 
888  // The same, but also use skipWhile()
889  {
890  std::unique_ptr<IOBuf> chain(IOBuf::create(16));
891  Appender app(chain.get(), 0);
892  app.push(StringPiece("hello123world456"));
893 
894  Cursor curs(chain.get());
895  EXPECT_STREQ("hello", curs.readWhile(isAlpha).c_str());
896  curs.skipWhile(isDigit);
897  curs.skipWhile(isAlpha);
898  EXPECT_STREQ("456", curs.readWhile(isDigit).c_str());
899  EXPECT_TRUE(curs.isAtEnd());
900  }
901 
902  // Test readWhile() using data split across multiple buffers,
903  // including some empty buffers in the middle of the chain.
904  {
905  std::unique_ptr<IOBuf> chain;
906 
907  // First element in the chain has "he"
908  auto buf = IOBuf::create(40);
909  Appender app(buf.get(), 0);
910  app.push(StringPiece("he"));
911  chain = std::move(buf);
912 
913  // The second element has "ll", after 10 bytes of headroom
914  buf = IOBuf::create(40);
915  buf->advance(10);
916  app = Appender{buf.get(), 0};
917  app.push(StringPiece("ll"));
918  chain->prependChain(std::move(buf));
919 
920  // The third element is empty
921  buf = IOBuf::create(40);
922  buf->advance(15);
923  chain->prependChain(std::move(buf));
924 
925  // The fourth element has "o12"
926  buf = IOBuf::create(40);
927  buf->advance(37);
928  app = Appender{buf.get(), 0};
929  app.push(StringPiece("o12"));
930  chain->prependChain(std::move(buf));
931 
932  // The fifth element has "3"
933  buf = IOBuf::create(40);
934  app = Appender{buf.get(), 0};
935  app.push(StringPiece("3"));
936  chain->prependChain(std::move(buf));
937 
938  // The sixth element is empty
939  buf = IOBuf::create(40);
940  chain->prependChain(std::move(buf));
941 
942  // The seventh element has "world456"
943  buf = IOBuf::create(40);
944  app = Appender{buf.get(), 0};
945  app.push(StringPiece("world456"));
946  chain->prependChain(std::move(buf));
947 
948  // The eighth element is empty
949  buf = IOBuf::create(40);
950  chain->prependChain(std::move(buf));
951 
952  Cursor curs(chain.get());
953  EXPECT_STREQ("hello", curs.readWhile(isAlpha).c_str());
954  EXPECT_STREQ("123", curs.readWhile(isDigit).c_str());
955  EXPECT_STREQ("world", curs.readWhile(isAlpha).c_str());
956  EXPECT_STREQ("456", curs.readWhile(isDigit).c_str());
957  EXPECT_TRUE(curs.isAtEnd());
958  }
959 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void push(const uint8_t *buf, size_t len)
Definition: Cursor.h:755
auto ch
#define EXPECT_STREQ(s1, s2)
Definition: gtest.h:1995
void prependChain(std::unique_ptr< IOBuf > &&iobuf)
Definition: IOBuf.cpp:509
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Range< const char * > StringPiece
TEST ( IOBuf  ,
TestAdvanceToEndSingle   
)

Definition at line 961 of file IOBufCursorTest.cpp.

References folly::io::detail::CursorBase< Derived, BufType >::advanceToEnd(), folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, and EXPECT_TRUE.

961  {
962  std::unique_ptr<IOBuf> chain(IOBuf::create(10));
963  chain->append(10);
964 
965  Cursor curs(chain.get());
966  curs.advanceToEnd();
967  EXPECT_TRUE(curs.isAtEnd());
968  EXPECT_EQ(curs - chain.get(), 10);
969 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( IOBuf  ,
TestAdvanceToEndMulti   
)

Definition at line 971 of file IOBufCursorTest.cpp.

References folly::io::detail::CursorBase< Derived, BufType >::advanceToEnd(), folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_TRUE, folly::gen::move, and folly::IOBuf::prependChain().

971  {
972  std::unique_ptr<IOBuf> chain(IOBuf::create(10));
973  chain->append(10);
974 
975  std::unique_ptr<IOBuf> buf(IOBuf::create(5));
976  buf->append(5);
977  chain->prependChain(std::move(buf));
978 
979  buf = IOBuf::create(20);
980  buf->append(20);
981  chain->prependChain(std::move(buf));
982 
983  Cursor curs(chain.get());
984  curs.advanceToEnd();
985  EXPECT_TRUE(curs.isAtEnd());
986  EXPECT_EQ(curs - chain.get(), 35);
987 
988  curs.reset(chain.get());
989  curs.skip(12);
990  curs.advanceToEnd();
991  EXPECT_TRUE(curs.isAtEnd());
992 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( IOBuf  ,
TestRetreatSingle   
)

Definition at line 994 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, and EXPECT_THROW.

994  {
995  std::unique_ptr<IOBuf> chain(IOBuf::create(20));
996  chain->append(20);
997 
998  Cursor curs(chain.get());
999  EXPECT_EQ(curs.retreatAtMost(0), 0);
1000  EXPECT_EQ(curs.totalLength(), 20);
1001  EXPECT_EQ(curs.retreatAtMost(5), 0);
1002  EXPECT_EQ(curs.totalLength(), 20);
1003  EXPECT_EQ(curs.retreatAtMost(25), 0);
1004  EXPECT_EQ(curs.totalLength(), 20);
1005 
1006  curs.retreat(0);
1007  EXPECT_THROW(curs.retreat(5), std::out_of_range);
1008  curs.reset(chain.get());
1009  EXPECT_THROW(curs.retreat(25), std::out_of_range);
1010  curs.reset(chain.get());
1011 
1012  curs.advanceToEnd();
1013  curs.retreat(5);
1014  EXPECT_EQ(curs.totalLength(), 5);
1015  curs.retreat(10);
1016  EXPECT_EQ(curs.totalLength(), 15);
1017  EXPECT_THROW(curs.retreat(10), std::out_of_range);
1018 
1019  curs.reset(chain.get());
1020  curs.advanceToEnd();
1021  EXPECT_EQ(curs.retreatAtMost(5), 5);
1022  EXPECT_EQ(curs.totalLength(), 5);
1023  EXPECT_EQ(curs.retreatAtMost(10), 10);
1024  EXPECT_EQ(curs.totalLength(), 15);
1025  EXPECT_EQ(curs.retreatAtMost(10), 5);
1026  EXPECT_EQ(curs.totalLength(), 20);
1027 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
TestRetreatMulti   
)

Definition at line 1029 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_THROW, folly::gen::move, and folly::IOBuf::prependChain().

1029  {
1030  std::unique_ptr<IOBuf> chain(IOBuf::create(10));
1031  chain->append(10);
1032 
1033  std::unique_ptr<IOBuf> buf(IOBuf::create(5));
1034  buf->append(5);
1035  chain->prependChain(std::move(buf));
1036 
1037  buf = IOBuf::create(20);
1038  buf->append(20);
1039  chain->prependChain(std::move(buf));
1040 
1041  Cursor curs(chain.get());
1042  EXPECT_EQ(curs.retreatAtMost(10), 0);
1043  EXPECT_THROW(curs.retreat(10), std::out_of_range);
1044  curs.reset(chain.get());
1045 
1046  curs.advanceToEnd();
1047  curs.retreat(20);
1048  EXPECT_EQ(curs.totalLength(), 20);
1049  EXPECT_EQ(curs.length(), 20);
1050  curs.retreat(1);
1051  EXPECT_EQ(curs.totalLength(), 21);
1052  EXPECT_EQ(curs.length(), 1);
1053  EXPECT_EQ(curs.retreatAtMost(50), 14);
1054  EXPECT_EQ(curs.totalLength(), 35);
1055 
1056  curs.advanceToEnd();
1057  curs.retreat(30);
1058  EXPECT_EQ(curs.totalLength(), 30);
1059 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
TEST ( IOBuf  ,
TestRetreatOperators   
)

Definition at line 1061 of file IOBufCursorTest.cpp.

References folly::io::detail::CursorBase< Derived, BufType >::advanceToEnd(), folly::IOBuf::append(), folly::IOBuf::create(), and EXPECT_EQ.

1061  {
1062  std::unique_ptr<IOBuf> chain(IOBuf::create(20));
1063  chain->append(20);
1064 
1065  Cursor curs(chain.get());
1066  curs.advanceToEnd();
1067  curs -= 5;
1068  EXPECT_EQ(curs.totalLength(), 5);
1069 
1070  curs.advanceToEnd();
1071  auto retreated = curs - 5;
1072  EXPECT_EQ(retreated.totalLength(), 5);
1073  EXPECT_EQ(curs.totalLength(), 0);
1074 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
tryRead   
)

Definition at line 1076 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, folly::IOBuf::isChained(), folly::gen::move, folly::IOBuf::prependChain(), uint16_t, uint32_t, uint64_t, and val.

1076  {
1077  unique_ptr<IOBuf> iobuf1(IOBuf::create(6));
1078  iobuf1->append(6);
1079  unique_ptr<IOBuf> iobuf2(IOBuf::create(24));
1080  iobuf2->append(24);
1081 
1082  iobuf1->prependChain(std::move(iobuf2));
1083 
1084  EXPECT_TRUE(iobuf1->isChained());
1085 
1086  RWPrivateCursor wcursor(iobuf1.get());
1087  Cursor rcursor(iobuf1.get());
1088  wcursor.writeLE((uint32_t)1);
1089  wcursor.writeLE((uint64_t)1);
1090  wcursor.writeLE((uint64_t)1);
1091  wcursor.writeLE((uint64_t)1);
1092  wcursor.writeLE((uint16_t)1);
1093  EXPECT_EQ(0, wcursor.totalLength());
1094 
1095  EXPECT_EQ(1u, rcursor.readLE<uint32_t>());
1096 
1097  EXPECT_EQ(1u, rcursor.readLE<uint32_t>());
1098  EXPECT_EQ(0u, rcursor.readLE<uint32_t>());
1099 
1100  EXPECT_EQ(1u, rcursor.readLE<uint32_t>());
1101  rcursor.skip(4);
1102 
1103  uint32_t val;
1104  EXPECT_TRUE(rcursor.tryRead(val));
1105  EXPECT_EQ(1, val);
1106  EXPECT_TRUE(rcursor.tryRead(val));
1107 
1108  EXPECT_EQ(0, val);
1109  EXPECT_FALSE(rcursor.tryRead(val));
1110 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
double val
Definition: String.cpp:273
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
tryReadLE   
)

Definition at line 1112 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, EXPECT_EQ, EXPECT_TRUE, folly::io::detail::CursorBase< Derived, BufType >::tryReadLE(), uint32_t, and folly::io::detail::Writable< Derived >::writeLE().

1112  {
1113  IOBuf buf{IOBuf::CREATE, 4};
1114  buf.append(4);
1115 
1116  RWPrivateCursor wcursor(&buf);
1117  Cursor rcursor(&buf);
1118 
1119  const uint32_t expected = 0x01020304;
1120  wcursor.writeLE(expected);
1121  uint32_t actual;
1122  EXPECT_TRUE(rcursor.tryReadLE(actual));
1123  EXPECT_EQ(expected, actual);
1124 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( IOBuf  ,
tryReadBE   
)

Definition at line 1126 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, EXPECT_EQ, EXPECT_TRUE, folly::io::detail::CursorBase< Derived, BufType >::tryReadBE(), uint32_t, and folly::io::detail::Writable< Derived >::writeBE().

1126  {
1127  IOBuf buf{IOBuf::CREATE, 4};
1128  buf.append(4);
1129 
1130  RWPrivateCursor wcursor(&buf);
1131  Cursor rcursor(&buf);
1132 
1133  const uint32_t expected = 0x01020304;
1134  wcursor.writeBE(expected);
1135  uint32_t actual;
1136  EXPECT_TRUE(rcursor.tryReadBE(actual));
1137  EXPECT_EQ(expected, actual);
1138 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( IOBuf  ,
tryReadConsumesAllInputOnFailure   
)

Definition at line 1140 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, EXPECT_EQ, EXPECT_FALSE, folly::io::detail::CursorBase< Derived, BufType >::totalLength(), folly::io::detail::CursorBase< Derived, BufType >::tryRead(), uint32_t, and val.

1140  {
1141  IOBuf buf{IOBuf::CREATE, 2};
1142  buf.append(2);
1143 
1144  Cursor rcursor(&buf);
1145  uint32_t val;
1146  EXPECT_FALSE(rcursor.tryRead(val));
1147  EXPECT_EQ(0, rcursor.totalLength());
1148 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
double val
Definition: String.cpp:273
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( IOBuf  ,
readConsumesAllInputOnFailure   
)

Definition at line 1150 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, EXPECT_EQ, EXPECT_THROW, folly::io::detail::CursorBase< Derived, BufType >::read(), folly::io::detail::CursorBase< Derived, BufType >::totalLength(), and uint32_t.

1150  {
1151  IOBuf buf{IOBuf::CREATE, 2};
1152  buf.append(2);
1153 
1154  Cursor rcursor(&buf);
1155  EXPECT_THROW(rcursor.read<uint32_t>(), std::out_of_range);
1156  EXPECT_EQ(0, rcursor.totalLength());
1157 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST ( IOBuf  ,
pushEmptyByteRange   
)

Definition at line 1159 of file IOBufCursorTest.cpp.

References folly::IOBuf::CREATE, EXPECT_EQ, and folly::io::detail::Writable< Derived >::push().

1159  {
1160  // Test pushing an empty ByteRange. This mainly tests that we do not
1161  // trigger UBSAN warnings by calling memcpy() with an null source pointer,
1162  // which is undefined behavior even if the length is 0.
1163  IOBuf buf{IOBuf::CREATE, 2};
1164  ByteRange emptyBytes;
1165 
1166  // Test calling Cursor::push()
1167  RWPrivateCursor wcursor(&buf);
1168  wcursor.push(emptyBytes);
1169  EXPECT_EQ(0, buf.computeChainDataLength());
1170 
1171  // Test calling Appender::push()
1172  Appender app(&buf, 16);
1173  app.push(emptyBytes);
1174  EXPECT_EQ(0, buf.computeChainDataLength());
1175 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Range< const unsigned char * > ByteRange
Definition: Range.h:1163
TEST ( IOBuf  ,
positionTracking   
)

Definition at line 1177 of file IOBufCursorTest.cpp.

References folly::IOBuf::append(), folly::IOBuf::create(), EXPECT_EQ, folly::gen::move, and folly::IOBuf::prependChain().

1177  {
1178  unique_ptr<IOBuf> iobuf1(IOBuf::create(6));
1179  iobuf1->append(6);
1180  unique_ptr<IOBuf> iobuf2(IOBuf::create(24));
1181  iobuf2->append(24);
1182  iobuf1->prependChain(std::move(iobuf2));
1183 
1184  Cursor cursor(iobuf1.get());
1185 
1186  EXPECT_EQ(0, cursor.getCurrentPosition());
1187  EXPECT_EQ(6, cursor.length());
1188 
1189  cursor.skip(3);
1190  EXPECT_EQ(3, cursor.getCurrentPosition());
1191  EXPECT_EQ(3, cursor.length());
1192 
1193  // Test that we properly handle advancing to the next chunk.
1194  cursor.skip(4);
1195  EXPECT_EQ(7, cursor.getCurrentPosition());
1196  EXPECT_EQ(23, cursor.length());
1197 
1198  // Test that we properly handle doing to the previous chunk.
1199  cursor.retreat(2);
1200  EXPECT_EQ(5, cursor.getCurrentPosition());
1201  EXPECT_EQ(1, cursor.length());
1202 
1203  // Test that we properly handle advanceToEnd
1204  cursor.advanceToEnd();
1205  EXPECT_EQ(30, cursor.getCurrentPosition());
1206  EXPECT_EQ(0, cursor.totalLength());
1207 
1208  // Reset to 0.
1209  cursor.reset(iobuf1.get());
1210  EXPECT_EQ(0, cursor.getCurrentPosition());
1211  EXPECT_EQ(30, cursor.totalLength());
1212 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567