proxygen
IOBufUtilTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <gtest/gtest.h>
10 
12 #include <folly/io/IOBuf.h>
13 
14 using namespace folly;
15 
16 namespace fizz {
17 namespace test {
18 
19 TEST(IOBufUtilTest, TrimBytes) {
20  auto buf = IOBuf::copyBuffer("hello");
21  buf->prependChain(IOBuf::copyBuffer("world"));
22  buf->prependChain(IOBuf::copyBuffer("I"));
23  buf->prependChain(IOBuf::create(0));
24  buf->prependChain(IOBuf::copyBuffer("speak"));
25 
26  auto expected = IOBuf::copyBuffer("Ispeak");
27  auto bufExpected = IOBuf::copyBuffer("helloworld");
28  auto bufLen = buf->computeChainDataLength();
29  constexpr size_t trimLen = 6;
30  std::array<uint8_t, trimLen> trimData;
31  folly::MutableByteRange trim(trimData);
32  trimBytes(*buf, trim);
33 
35  EXPECT_EQ(expected->coalesce(), trim.castToConst());
36  EXPECT_EQ(bufLen - trimLen, buf->computeChainDataLength());
37  EXPECT_TRUE(eq(bufExpected, buf));
38 }
39 
40 TEST(IOBufUtilTest, TransformBufferInplace) {
41  auto buf = IOBuf::copyBuffer("hello");
42  buf->prependChain(IOBuf::copyBuffer("world"));
43  buf->prependChain(IOBuf::copyBuffer("I"));
44  buf->prependChain(IOBuf::create(0));
45  buf->prependChain(IOBuf::copyBuffer("speak"));
46 
47  auto expected = IOBuf::create(buf->computeChainDataLength());
48  expected->append(buf->computeChainDataLength());
49  memset(expected->writableData(), 'w', expected->length());
50 
52  *buf, *buf, [](uint8_t* out, const uint8_t* /*in*/, size_t len) {
53  memset(out, 'w', len);
54  });
56  EXPECT_TRUE(eq(expected, buf));
57 }
58 
59 std::unique_ptr<IOBuf> createBuf(size_t len) {
60  auto res = IOBuf::create(len);
61  res->append(len);
62  return res;
63 }
64 
65 TEST(IOBufUtilTest, TransformBufferWithFragmentedBuffer) {
66  auto buf = IOBuf::copyBuffer("hello");
67  buf->prependChain(IOBuf::copyBuffer("world"));
68  buf->prependChain(IOBuf::copyBuffer("I"));
69  buf->prependChain(IOBuf::create(0));
70  buf->prependChain(IOBuf::copyBuffer("speak"));
71 
72  // needs to add up to 16
73  auto fragmented = createBuf(3);
74  auto fragment1 = createBuf(6);
75  auto fragment2 = createBuf(0);
76  auto fragment3 = createBuf(2);
77  auto fragment4 = createBuf(4);
78  auto fragment5 = createBuf(1);
79 
80  fragmented->prependChain(std::move(fragment1));
81  fragmented->prependChain(std::move(fragment2));
82  fragmented->prependChain(std::move(fragment3));
83  fragmented->prependChain(std::move(fragment4));
84  fragmented->prependChain(std::move(fragment5));
85 
87  *buf, *fragmented, [](uint8_t* out, const uint8_t* in, size_t len) {
88  memcpy(out, in, len);
89  });
91  EXPECT_TRUE(eq(buf, fragmented));
92 }
93 
94 struct BlockWriter {
95  size_t copy(uint8_t* out, const uint8_t* in, size_t len) {
96  if (len + internalOffset < 8) {
97  // still not enough for a block
98  memcpy(block + internalOffset, in, len);
99  internalOffset += len;
100  // nothing copied to out
101  return 0;
102  }
103  size_t outOffset = 0;
104  // need to copy in block chunks
105  auto numToWrite = 8 * ((internalOffset + len) / 8);
106  if (internalOffset > 0) {
107  memcpy(out, block, internalOffset);
108  outOffset += internalOffset;
109  numToWrite -= internalOffset;
110  internalOffset = 0;
111  }
112 
113  // copy the rest
114  memcpy(out + outOffset, in, numToWrite);
115  // check if we need to internal buffer anything left
116  if (len > numToWrite) {
117  auto numToBuf = len - numToWrite;
118  DCHECK(numToBuf < 8);
119  memcpy(block, in + numToWrite, numToBuf);
120  internalOffset = numToBuf;
121  }
122  return numToWrite + outOffset;
123  }
124 
125  size_t internalOffset = 0;
126  uint8_t block[8] = {0};
127 };
128 
129 TEST(IOBufUtilTest, TransformBufferBlocks) {
130  // 2 blocks of size 8
131  auto buf = IOBuf::copyBuffer("0000111122223333");
132  auto output = createBuf(16);
133 
134  BlockWriter writer;
135  transformBufferBlocks<8>(
136  *buf, *output, [&writer](uint8_t* out, const uint8_t* in, size_t len) {
137  return writer.copy(out, in, len);
138  });
140  EXPECT_TRUE(eq(buf, output));
141 }
142 
143 TEST(IOBufUtilTest, TransformBufferBlocksSplit) {
144  // 1 block of size 8
145  auto buf = IOBuf::copyBuffer("0000");
146  buf->prependChain(IOBuf::copyBuffer("1111"));
147  auto output = createBuf(4);
148  auto fragment1 = createBuf(4);
149  output->prependChain(std::move(fragment1));
150 
151  BlockWriter writer;
152  transformBufferBlocks<8>(
153  *buf, *output, [&writer](uint8_t* out, const uint8_t* in, size_t len) {
154  return writer.copy(out, in, len);
155  });
157  EXPECT_TRUE(eq(buf, output));
158 }
159 
160 TEST(IOBufUtilTest, TransformBufferBlocksInputFragmented) {
161  // do 3 blocks
162  auto buf = IOBuf::copyBuffer("00");
163  buf->prependChain(IOBuf::copyBuffer("00"));
164  buf->prependChain(IOBuf::copyBuffer("1"));
165  buf->prependChain(IOBuf::create(0));
166  buf->prependChain(IOBuf::copyBuffer("11122223"));
167  buf->prependChain(IOBuf::copyBuffer("33344"));
168  buf->prependChain(IOBuf::copyBuffer("44"));
169  buf->prependChain(IOBuf::copyBuffer("5555"));
170 
171  auto output = IOBuf::create(24);
172  output->append(24);
173 
174  BlockWriter writer;
175  transformBufferBlocks<8>(
176  *buf, *output, [&writer](uint8_t* out, const uint8_t* in, size_t len) {
177  return writer.copy(out, in, len);
178  });
180  EXPECT_TRUE(eq(buf, output));
181 }
182 
183 TEST(IOBufUtilTest, TransformBufferBlocksOutputFragmented) {
184  // 3 blocks of 8
185  auto buf = IOBuf::copyBuffer("fizzbuzzfizzbuzzfizzbuzz");
186 
187  // needs to add up to 24
188  auto output = createBuf(3);
189  output->prependChain(createBuf(6));
190  output->prependChain(createBuf(0));
191  output->prependChain(createBuf(2));
192  output->prependChain(createBuf(4));
193  output->prependChain(createBuf(1));
194  output->prependChain(createBuf(1));
195  output->prependChain(createBuf(7));
196 
197  BlockWriter writer;
198  transformBufferBlocks<8>(
199  *buf, *output, [&writer](uint8_t* out, const uint8_t* in, size_t len) {
200  return writer.copy(out, in, len);
201  });
203  EXPECT_TRUE(eq(buf, output));
204 }
205 
206 TEST(IOBufUtilTest, TransformBufferBlocksInputFragmented2) {
207  auto buf = IOBuf::copyBuffer("1111111122222222");
208  auto output = createBuf(10);
209  output->prependChain(createBuf(6));
210  BlockWriter writer;
211  transformBufferBlocks<8>(
212  *buf, *output, [&writer](uint8_t* out, const uint8_t* in, size_t len) {
213  return writer.copy(out, in, len);
214  });
216  EXPECT_TRUE(eq(buf, output));
217 }
218 
219 TEST(IOBufUtilTest, TransformBufferBlocksFragmented) {
220  auto buf = IOBuf::copyBuffer("00");
221  buf->prependChain(IOBuf::copyBuffer("00"));
222  buf->prependChain(IOBuf::copyBuffer("1"));
223  buf->prependChain(IOBuf::create(0));
224  buf->prependChain(IOBuf::copyBuffer("11122223"));
225  buf->prependChain(IOBuf::copyBuffer("33344"));
226  buf->prependChain(IOBuf::copyBuffer("44"));
227  buf->prependChain(IOBuf::copyBuffer("5555"));
228 
229  // needs to add up to 24
230  auto output = createBuf(3);
231  output->prependChain(createBuf(6));
232  output->prependChain(createBuf(0));
233  output->prependChain(createBuf(2));
234  output->prependChain(createBuf(4));
235  output->prependChain(createBuf(1));
236  output->prependChain(createBuf(1));
237  output->prependChain(createBuf(7));
238 
239  BlockWriter writer;
240  transformBufferBlocks<8>(
241  *buf, *output, [&writer](uint8_t* out, const uint8_t* in, size_t len) {
242  return writer.copy(out, in, len);
243  });
245  EXPECT_TRUE(eq(buf, output));
246 }
247 
248 } // namespace test
249 } // namespace fizz
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
void trimBytes(IOBuf &buf, folly::MutableByteRange trimmed)
Definition: IOBufUtil.cpp:15
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void transformBuffer(const folly::IOBuf &in, folly::IOBuf &out, Func func)
Definition: IOBufUtil.h:38
Definition: Actions.h:16
const_range_type castToConst() const
Definition: Range.h:598
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
std::unique_ptr< IOBuf > createBuf(size_t len)
static std::unique_ptr< IOBuf > copyBuffer(const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
Definition: IOBuf.h:1587
TEST(SequencedExecutor, CPUThreadPoolExecutor)
size_t copy(uint8_t *out, const uint8_t *in, size_t len)