2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include <gtest/gtest.h>
18 #include <folly/wangle/codec/FixedLengthFrameDecoder.h>
19 #include <folly/wangle/codec/LengthFieldBasedFrameDecoder.h>
20 #include <folly/wangle/codec/LengthFieldPrepender.h>
22 using namespace folly;
23 using namespace folly::wangle;
24 using namespace folly::io;
27 : public BytesToBytesHandler {
29 FrameTester(std::function<void(std::unique_ptr<IOBuf>)> test)
32 void read(Context* ctx, IOBufQueue& q) {
36 std::function<void(std::unique_ptr<IOBuf>)> test_;
40 : public BytesToBytesHandler {
43 Future<void> write(Context* ctx, std::unique_ptr<IOBuf> buf) {
44 IOBufQueue q_(IOBufQueue::cacheChainLength());
45 q_.append(std::move(buf));
52 TEST(CodecTest, FixedLengthFrameDecoder) {
53 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
57 .addBack(FixedLengthFrameDecoder(10))
58 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
59 auto sz = buf->computeChainDataLength();
65 auto buf3 = IOBuf::create(3);
67 auto buf11 = IOBuf::create(11);
69 auto buf16 = IOBuf::create(16);
72 IOBufQueue q(IOBufQueue::cacheChainLength());
74 q.append(std::move(buf3));
78 q.append(std::move(buf11));
82 q.append(std::move(buf16));
87 TEST(CodecTest, LengthFieldFramePipeline) {
88 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
92 .addBack(BytesReflector())
93 .addBack(LengthFieldBasedFrameDecoder())
94 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
95 auto sz = buf->computeChainDataLength();
99 .addBack(LengthFieldPrepender())
102 auto buf = IOBuf::create(2);
104 pipeline.write(std::move(buf));
105 EXPECT_EQ(called, 1);
108 TEST(CodecTest, LengthFieldFramePipelineLittleEndian) {
109 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
113 .addBack(BytesReflector())
114 .addBack(LengthFieldBasedFrameDecoder(4, 100, 0, 0, 4, false))
115 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
116 auto sz = buf->computeChainDataLength();
120 .addBack(LengthFieldPrepender(4, 0, false, false))
123 auto buf = IOBuf::create(1);
125 pipeline.write(std::move(buf));
126 EXPECT_EQ(called, 1);
129 TEST(CodecTest, LengthFieldFrameDecoderSimple) {
130 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
134 .addBack(LengthFieldBasedFrameDecoder())
135 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
136 auto sz = buf->computeChainDataLength();
142 auto bufFrame = IOBuf::create(4);
144 RWPrivateCursor c(bufFrame.get());
145 c.writeBE((uint32_t)1);
146 auto bufData = IOBuf::create(1);
149 IOBufQueue q(IOBufQueue::cacheChainLength());
151 q.append(std::move(bufFrame));
153 EXPECT_EQ(called, 0);
155 q.append(std::move(bufData));
157 EXPECT_EQ(called, 1);
160 TEST(CodecTest, LengthFieldFrameDecoderNoStrip) {
161 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
165 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, 0, 0))
166 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
167 auto sz = buf->computeChainDataLength();
173 auto bufFrame = IOBuf::create(2);
175 RWPrivateCursor c(bufFrame.get());
176 c.writeBE((uint16_t)1);
177 auto bufData = IOBuf::create(1);
180 IOBufQueue q(IOBufQueue::cacheChainLength());
182 q.append(std::move(bufFrame));
184 EXPECT_EQ(called, 0);
186 q.append(std::move(bufData));
188 EXPECT_EQ(called, 1);
191 TEST(CodecTest, LengthFieldFrameDecoderAdjustment) {
192 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
196 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, -2, 0))
197 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
198 auto sz = buf->computeChainDataLength();
204 auto bufFrame = IOBuf::create(2);
206 RWPrivateCursor c(bufFrame.get());
207 c.writeBE((uint16_t)3); // includes frame size
208 auto bufData = IOBuf::create(1);
211 IOBufQueue q(IOBufQueue::cacheChainLength());
213 q.append(std::move(bufFrame));
215 EXPECT_EQ(called, 0);
217 q.append(std::move(bufData));
219 EXPECT_EQ(called, 1);
222 TEST(CodecTest, LengthFieldFrameDecoderPreHeader) {
223 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
227 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, 0, 0))
228 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
229 auto sz = buf->computeChainDataLength();
235 auto bufFrame = IOBuf::create(4);
237 RWPrivateCursor c(bufFrame.get());
238 c.write((uint16_t)100); // header
239 c.writeBE((uint16_t)1); // frame size
240 auto bufData = IOBuf::create(1);
243 IOBufQueue q(IOBufQueue::cacheChainLength());
245 q.append(std::move(bufFrame));
247 EXPECT_EQ(called, 0);
249 q.append(std::move(bufData));
251 EXPECT_EQ(called, 1);
254 TEST(CodecTest, LengthFieldFrameDecoderPostHeader) {
255 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
259 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, 2, 0))
260 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
261 auto sz = buf->computeChainDataLength();
267 auto bufFrame = IOBuf::create(4);
269 RWPrivateCursor c(bufFrame.get());
270 c.writeBE((uint16_t)1); // frame size
271 c.write((uint16_t)100); // header
272 auto bufData = IOBuf::create(1);
275 IOBufQueue q(IOBufQueue::cacheChainLength());
277 q.append(std::move(bufFrame));
279 EXPECT_EQ(called, 0);
281 q.append(std::move(bufData));
283 EXPECT_EQ(called, 1);
286 TEST(CodecTest, LengthFieldFrameDecoderStripPrePostHeader) {
287 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
291 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, 2, 4))
292 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
293 auto sz = buf->computeChainDataLength();
299 auto bufFrame = IOBuf::create(6);
301 RWPrivateCursor c(bufFrame.get());
302 c.write((uint16_t)100); // pre header
303 c.writeBE((uint16_t)1); // frame size
304 c.write((uint16_t)100); // post header
305 auto bufData = IOBuf::create(1);
308 IOBufQueue q(IOBufQueue::cacheChainLength());
310 q.append(std::move(bufFrame));
312 EXPECT_EQ(called, 0);
314 q.append(std::move(bufData));
316 EXPECT_EQ(called, 1);
319 TEST(CodecTest, LengthFieldFrameDecoderStripPrePostHeaderFrameInclHeader) {
320 ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
324 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, -2, 4))
325 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
326 auto sz = buf->computeChainDataLength();
332 auto bufFrame = IOBuf::create(6);
334 RWPrivateCursor c(bufFrame.get());
335 c.write((uint16_t)100); // pre header
336 c.writeBE((uint16_t)5); // frame size
337 c.write((uint16_t)100); // post header
338 auto bufData = IOBuf::create(1);
341 IOBufQueue q(IOBufQueue::cacheChainLength());
343 q.append(std::move(bufFrame));
345 EXPECT_EQ(called, 0);
347 q.append(std::move(bufData));
349 EXPECT_EQ(called, 1);