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>
21 #include <folly/wangle/codec/LineBasedFrameDecoder.h>
23 using namespace folly;
24 using namespace folly::wangle;
25 using namespace folly::io;
28 : public InboundHandler<std::unique_ptr<IOBuf>> {
30 explicit FrameTester(std::function<void(std::unique_ptr<IOBuf>)> test)
33 void read(Context* ctx, std::unique_ptr<IOBuf> buf) override {
34 test_(std::move(buf));
37 void readException(Context* ctx, exception_wrapper w) override {
41 std::function<void(std::unique_ptr<IOBuf>)> test_;
45 : public BytesToBytesHandler {
47 Future<Unit> write(Context* ctx, std::unique_ptr<IOBuf> buf) override {
48 IOBufQueue q_(IOBufQueue::cacheChainLength());
49 q_.append(std::move(buf));
56 TEST(FixedLengthFrameDecoder, FailWhenLengthFieldEndOffset) {
57 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
61 .addBack(FixedLengthFrameDecoder(10))
62 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
63 auto sz = buf->computeChainDataLength();
69 auto buf3 = IOBuf::create(3);
71 auto buf11 = IOBuf::create(11);
73 auto buf16 = IOBuf::create(16);
76 IOBufQueue q(IOBufQueue::cacheChainLength());
78 q.append(std::move(buf3));
82 q.append(std::move(buf11));
86 q.append(std::move(buf16));
91 TEST(LengthFieldFramePipeline, SimpleTest) {
92 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
96 .addBack(BytesReflector())
97 .addBack(LengthFieldPrepender())
98 .addBack(LengthFieldBasedFrameDecoder())
99 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
100 auto sz = buf->computeChainDataLength();
106 auto buf = IOBuf::create(2);
108 pipeline.write(std::move(buf));
109 EXPECT_EQ(called, 1);
112 TEST(LengthFieldFramePipeline, LittleEndian) {
113 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
117 .addBack(BytesReflector())
118 .addBack(LengthFieldBasedFrameDecoder(4, 100, 0, 0, 4, false))
119 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
120 auto sz = buf->computeChainDataLength();
124 .addBack(LengthFieldPrepender(4, 0, false, false))
127 auto buf = IOBuf::create(1);
129 pipeline.write(std::move(buf));
130 EXPECT_EQ(called, 1);
133 TEST(LengthFieldFrameDecoder, Simple) {
134 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
138 .addBack(LengthFieldBasedFrameDecoder())
139 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
140 auto sz = buf->computeChainDataLength();
146 auto bufFrame = IOBuf::create(4);
148 RWPrivateCursor c(bufFrame.get());
149 c.writeBE((uint32_t)1);
150 auto bufData = IOBuf::create(1);
153 IOBufQueue q(IOBufQueue::cacheChainLength());
155 q.append(std::move(bufFrame));
157 EXPECT_EQ(called, 0);
159 q.append(std::move(bufData));
161 EXPECT_EQ(called, 1);
164 TEST(LengthFieldFrameDecoder, NoStrip) {
165 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
169 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, 0, 0))
170 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
171 auto sz = buf->computeChainDataLength();
177 auto bufFrame = IOBuf::create(2);
179 RWPrivateCursor c(bufFrame.get());
180 c.writeBE((uint16_t)1);
181 auto bufData = IOBuf::create(1);
184 IOBufQueue q(IOBufQueue::cacheChainLength());
186 q.append(std::move(bufFrame));
188 EXPECT_EQ(called, 0);
190 q.append(std::move(bufData));
192 EXPECT_EQ(called, 1);
195 TEST(LengthFieldFrameDecoder, Adjustment) {
196 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
200 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, -2, 0))
201 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
202 auto sz = buf->computeChainDataLength();
208 auto bufFrame = IOBuf::create(2);
210 RWPrivateCursor c(bufFrame.get());
211 c.writeBE((uint16_t)3); // includes frame size
212 auto bufData = IOBuf::create(1);
215 IOBufQueue q(IOBufQueue::cacheChainLength());
217 q.append(std::move(bufFrame));
219 EXPECT_EQ(called, 0);
221 q.append(std::move(bufData));
223 EXPECT_EQ(called, 1);
226 TEST(LengthFieldFrameDecoder, PreHeader) {
227 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
231 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, 0, 0))
232 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
233 auto sz = buf->computeChainDataLength();
239 auto bufFrame = IOBuf::create(4);
241 RWPrivateCursor c(bufFrame.get());
242 c.write((uint16_t)100); // header
243 c.writeBE((uint16_t)1); // frame size
244 auto bufData = IOBuf::create(1);
247 IOBufQueue q(IOBufQueue::cacheChainLength());
249 q.append(std::move(bufFrame));
251 EXPECT_EQ(called, 0);
253 q.append(std::move(bufData));
255 EXPECT_EQ(called, 1);
258 TEST(LengthFieldFrameDecoder, PostHeader) {
259 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
263 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, 2, 0))
264 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
265 auto sz = buf->computeChainDataLength();
271 auto bufFrame = IOBuf::create(4);
273 RWPrivateCursor c(bufFrame.get());
274 c.writeBE((uint16_t)1); // frame size
275 c.write((uint16_t)100); // header
276 auto bufData = IOBuf::create(1);
279 IOBufQueue q(IOBufQueue::cacheChainLength());
281 q.append(std::move(bufFrame));
283 EXPECT_EQ(called, 0);
285 q.append(std::move(bufData));
287 EXPECT_EQ(called, 1);
290 TEST(LengthFieldFrameDecoderStrip, PrePostHeader) {
291 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
295 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, 2, 4))
296 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
297 auto sz = buf->computeChainDataLength();
303 auto bufFrame = IOBuf::create(6);
305 RWPrivateCursor c(bufFrame.get());
306 c.write((uint16_t)100); // pre header
307 c.writeBE((uint16_t)1); // frame size
308 c.write((uint16_t)100); // post header
309 auto bufData = IOBuf::create(1);
312 IOBufQueue q(IOBufQueue::cacheChainLength());
314 q.append(std::move(bufFrame));
316 EXPECT_EQ(called, 0);
318 q.append(std::move(bufData));
320 EXPECT_EQ(called, 1);
323 TEST(LengthFieldFrameDecoder, StripPrePostHeaderFrameInclHeader) {
324 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
328 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, -2, 4))
329 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
330 auto sz = buf->computeChainDataLength();
336 auto bufFrame = IOBuf::create(6);
338 RWPrivateCursor c(bufFrame.get());
339 c.write((uint16_t)100); // pre header
340 c.writeBE((uint16_t)5); // frame size
341 c.write((uint16_t)100); // post header
342 auto bufData = IOBuf::create(1);
345 IOBufQueue q(IOBufQueue::cacheChainLength());
347 q.append(std::move(bufFrame));
349 EXPECT_EQ(called, 0);
351 q.append(std::move(bufData));
353 EXPECT_EQ(called, 1);
356 TEST(LengthFieldFrameDecoder, FailTestLengthFieldEndOffset) {
357 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
361 .addBack(LengthFieldBasedFrameDecoder(4, 10, 4, -2, 4))
362 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
363 ASSERT_EQ(nullptr, buf);
368 auto bufFrame = IOBuf::create(8);
370 RWPrivateCursor c(bufFrame.get());
371 c.writeBE((uint32_t)0); // frame size
372 c.write((uint32_t)0); // crap
374 IOBufQueue q(IOBufQueue::cacheChainLength());
376 q.append(std::move(bufFrame));
378 EXPECT_EQ(called, 1);
381 TEST(LengthFieldFrameDecoder, FailTestLengthFieldFrameSize) {
382 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
386 .addBack(LengthFieldBasedFrameDecoder(4, 10, 0, 0, 4))
387 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
388 ASSERT_EQ(nullptr, buf);
393 auto bufFrame = IOBuf::create(16);
394 bufFrame->append(16);
395 RWPrivateCursor c(bufFrame.get());
396 c.writeBE((uint32_t)12); // frame size
397 c.write((uint32_t)0); // nothing
398 c.write((uint32_t)0); // nothing
399 c.write((uint32_t)0); // nothing
401 IOBufQueue q(IOBufQueue::cacheChainLength());
403 q.append(std::move(bufFrame));
405 EXPECT_EQ(called, 1);
408 TEST(LengthFieldFrameDecoder, FailTestLengthFieldInitialBytes) {
409 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
413 .addBack(LengthFieldBasedFrameDecoder(4, 10, 0, 0, 10))
414 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
415 ASSERT_EQ(nullptr, buf);
420 auto bufFrame = IOBuf::create(16);
421 bufFrame->append(16);
422 RWPrivateCursor c(bufFrame.get());
423 c.writeBE((uint32_t)4); // frame size
424 c.write((uint32_t)0); // nothing
425 c.write((uint32_t)0); // nothing
426 c.write((uint32_t)0); // nothing
428 IOBufQueue q(IOBufQueue::cacheChainLength());
430 q.append(std::move(bufFrame));
432 EXPECT_EQ(called, 1);
435 TEST(LineBasedFrameDecoder, Simple) {
436 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
440 .addBack(LineBasedFrameDecoder(10))
441 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
442 auto sz = buf->computeChainDataLength();
448 auto buf = IOBuf::create(3);
451 IOBufQueue q(IOBufQueue::cacheChainLength());
453 q.append(std::move(buf));
455 EXPECT_EQ(called, 0);
457 buf = IOBuf::create(1);
459 RWPrivateCursor c(buf.get());
461 q.append(std::move(buf));
463 EXPECT_EQ(called, 1);
465 buf = IOBuf::create(4);
467 RWPrivateCursor c1(buf.get());
473 q.append(std::move(buf));
475 EXPECT_EQ(called, 1);
477 buf = IOBuf::create(1);
479 RWPrivateCursor c2(buf.get());
481 q.append(std::move(buf));
483 EXPECT_EQ(called, 2);
486 TEST(LineBasedFrameDecoder, SaveDelimiter) {
487 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
491 .addBack(LineBasedFrameDecoder(10, false))
492 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
493 auto sz = buf->computeChainDataLength();
499 auto buf = IOBuf::create(3);
502 IOBufQueue q(IOBufQueue::cacheChainLength());
504 q.append(std::move(buf));
506 EXPECT_EQ(called, 0);
508 buf = IOBuf::create(1);
510 RWPrivateCursor c(buf.get());
512 q.append(std::move(buf));
514 EXPECT_EQ(called, 1);
516 buf = IOBuf::create(3);
518 RWPrivateCursor c1(buf.get());
522 q.append(std::move(buf));
524 EXPECT_EQ(called, 1);
526 buf = IOBuf::create(1);
528 RWPrivateCursor c2(buf.get());
530 q.append(std::move(buf));
532 EXPECT_EQ(called, 2);
535 TEST(LineBasedFrameDecoder, Fail) {
536 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
540 .addBack(LineBasedFrameDecoder(10))
541 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
542 ASSERT_EQ(nullptr, buf);
547 auto buf = IOBuf::create(11);
550 IOBufQueue q(IOBufQueue::cacheChainLength());
552 q.append(std::move(buf));
554 EXPECT_EQ(called, 1);
556 buf = IOBuf::create(1);
558 q.append(std::move(buf));
560 EXPECT_EQ(called, 1);
562 buf = IOBuf::create(2);
564 RWPrivateCursor c(buf.get());
567 q.append(std::move(buf));
569 EXPECT_EQ(called, 1);
571 buf = IOBuf::create(12);
573 RWPrivateCursor c2(buf.get());
574 for (int i = 0; i < 11; i++) {
577 c2.write<char>('\n');
578 q.append(std::move(buf));
580 EXPECT_EQ(called, 2);
583 TEST(LineBasedFrameDecoder, NewLineOnly) {
584 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
588 .addBack(LineBasedFrameDecoder(
589 10, true, LineBasedFrameDecoder::TerminatorType::NEWLINE))
590 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
591 auto sz = buf->computeChainDataLength();
597 auto buf = IOBuf::create(2);
599 RWPrivateCursor c(buf.get());
603 IOBufQueue q(IOBufQueue::cacheChainLength());
605 q.append(std::move(buf));
607 EXPECT_EQ(called, 1);
610 TEST(LineBasedFrameDecoder, CarriageNewLineOnly) {
611 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
615 .addBack(LineBasedFrameDecoder(
616 10, true, LineBasedFrameDecoder::TerminatorType::CARRIAGENEWLINE))
617 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
618 auto sz = buf->computeChainDataLength();
624 auto buf = IOBuf::create(3);
626 RWPrivateCursor c(buf.get());
631 IOBufQueue q(IOBufQueue::cacheChainLength());
633 q.append(std::move(buf));
635 EXPECT_EQ(called, 1);