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 BytesToBytesHandler {
30 FrameTester(std::function<void(std::unique_ptr<IOBuf>)> test)
33 void read(Context* ctx, IOBufQueue& q) {
37 void readException(Context* ctx, exception_wrapper w) {
41 std::function<void(std::unique_ptr<IOBuf>)> test_;
45 : public BytesToBytesHandler {
48 Future<void> write(Context* ctx, std::unique_ptr<IOBuf> buf) {
49 IOBufQueue q_(IOBufQueue::cacheChainLength());
50 q_.append(std::move(buf));
57 TEST(FixedLengthFrameDecoder, FailWhenLengthFieldEndOffset) {
58 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
62 .addBack(FixedLengthFrameDecoder(10))
63 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
64 auto sz = buf->computeChainDataLength();
70 auto buf3 = IOBuf::create(3);
72 auto buf11 = IOBuf::create(11);
74 auto buf16 = IOBuf::create(16);
77 IOBufQueue q(IOBufQueue::cacheChainLength());
79 q.append(std::move(buf3));
83 q.append(std::move(buf11));
87 q.append(std::move(buf16));
92 TEST(LengthFieldFramePipeline, SimpleTest) {
93 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
97 .addBack(BytesReflector())
98 .addBack(LengthFieldBasedFrameDecoder())
99 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
100 auto sz = buf->computeChainDataLength();
104 .addBack(LengthFieldPrepender())
107 auto buf = IOBuf::create(2);
109 pipeline.write(std::move(buf));
110 EXPECT_EQ(called, 1);
113 TEST(LengthFieldFramePipeline, LittleEndian) {
114 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
118 .addBack(BytesReflector())
119 .addBack(LengthFieldBasedFrameDecoder(4, 100, 0, 0, 4, false))
120 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
121 auto sz = buf->computeChainDataLength();
125 .addBack(LengthFieldPrepender(4, 0, false, false))
128 auto buf = IOBuf::create(1);
130 pipeline.write(std::move(buf));
131 EXPECT_EQ(called, 1);
134 TEST(LengthFieldFrameDecoder, Simple) {
135 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
139 .addBack(LengthFieldBasedFrameDecoder())
140 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
141 auto sz = buf->computeChainDataLength();
147 auto bufFrame = IOBuf::create(4);
149 RWPrivateCursor c(bufFrame.get());
150 c.writeBE((uint32_t)1);
151 auto bufData = IOBuf::create(1);
154 IOBufQueue q(IOBufQueue::cacheChainLength());
156 q.append(std::move(bufFrame));
158 EXPECT_EQ(called, 0);
160 q.append(std::move(bufData));
162 EXPECT_EQ(called, 1);
165 TEST(LengthFieldFrameDecoder, NoStrip) {
166 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
170 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, 0, 0))
171 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
172 auto sz = buf->computeChainDataLength();
178 auto bufFrame = IOBuf::create(2);
180 RWPrivateCursor c(bufFrame.get());
181 c.writeBE((uint16_t)1);
182 auto bufData = IOBuf::create(1);
185 IOBufQueue q(IOBufQueue::cacheChainLength());
187 q.append(std::move(bufFrame));
189 EXPECT_EQ(called, 0);
191 q.append(std::move(bufData));
193 EXPECT_EQ(called, 1);
196 TEST(LengthFieldFrameDecoder, Adjustment) {
197 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
201 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, -2, 0))
202 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
203 auto sz = buf->computeChainDataLength();
209 auto bufFrame = IOBuf::create(2);
211 RWPrivateCursor c(bufFrame.get());
212 c.writeBE((uint16_t)3); // includes frame size
213 auto bufData = IOBuf::create(1);
216 IOBufQueue q(IOBufQueue::cacheChainLength());
218 q.append(std::move(bufFrame));
220 EXPECT_EQ(called, 0);
222 q.append(std::move(bufData));
224 EXPECT_EQ(called, 1);
227 TEST(LengthFieldFrameDecoder, PreHeader) {
228 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
232 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, 0, 0))
233 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
234 auto sz = buf->computeChainDataLength();
240 auto bufFrame = IOBuf::create(4);
242 RWPrivateCursor c(bufFrame.get());
243 c.write((uint16_t)100); // header
244 c.writeBE((uint16_t)1); // frame size
245 auto bufData = IOBuf::create(1);
248 IOBufQueue q(IOBufQueue::cacheChainLength());
250 q.append(std::move(bufFrame));
252 EXPECT_EQ(called, 0);
254 q.append(std::move(bufData));
256 EXPECT_EQ(called, 1);
259 TEST(LengthFieldFrameDecoder, PostHeader) {
260 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
264 .addBack(LengthFieldBasedFrameDecoder(2, 10, 0, 2, 0))
265 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
266 auto sz = buf->computeChainDataLength();
272 auto bufFrame = IOBuf::create(4);
274 RWPrivateCursor c(bufFrame.get());
275 c.writeBE((uint16_t)1); // frame size
276 c.write((uint16_t)100); // header
277 auto bufData = IOBuf::create(1);
280 IOBufQueue q(IOBufQueue::cacheChainLength());
282 q.append(std::move(bufFrame));
284 EXPECT_EQ(called, 0);
286 q.append(std::move(bufData));
288 EXPECT_EQ(called, 1);
291 TEST(LengthFieldFrameDecoderStrip, PrePostHeader) {
292 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
296 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, 2, 4))
297 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
298 auto sz = buf->computeChainDataLength();
304 auto bufFrame = IOBuf::create(6);
306 RWPrivateCursor c(bufFrame.get());
307 c.write((uint16_t)100); // pre header
308 c.writeBE((uint16_t)1); // frame size
309 c.write((uint16_t)100); // post header
310 auto bufData = IOBuf::create(1);
313 IOBufQueue q(IOBufQueue::cacheChainLength());
315 q.append(std::move(bufFrame));
317 EXPECT_EQ(called, 0);
319 q.append(std::move(bufData));
321 EXPECT_EQ(called, 1);
324 TEST(LengthFieldFrameDecoder, StripPrePostHeaderFrameInclHeader) {
325 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
329 .addBack(LengthFieldBasedFrameDecoder(2, 10, 2, -2, 4))
330 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
331 auto sz = buf->computeChainDataLength();
337 auto bufFrame = IOBuf::create(6);
339 RWPrivateCursor c(bufFrame.get());
340 c.write((uint16_t)100); // pre header
341 c.writeBE((uint16_t)5); // frame size
342 c.write((uint16_t)100); // post header
343 auto bufData = IOBuf::create(1);
346 IOBufQueue q(IOBufQueue::cacheChainLength());
348 q.append(std::move(bufFrame));
350 EXPECT_EQ(called, 0);
352 q.append(std::move(bufData));
354 EXPECT_EQ(called, 1);
357 TEST(LengthFieldFrameDecoder, FailTestLengthFieldEndOffset) {
358 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
362 .addBack(LengthFieldBasedFrameDecoder(4, 10, 4, -2, 4))
363 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
364 ASSERT_EQ(nullptr, buf);
369 auto bufFrame = IOBuf::create(8);
371 RWPrivateCursor c(bufFrame.get());
372 c.writeBE((uint32_t)0); // frame size
373 c.write((uint32_t)0); // crap
375 IOBufQueue q(IOBufQueue::cacheChainLength());
377 q.append(std::move(bufFrame));
379 EXPECT_EQ(called, 1);
382 TEST(LengthFieldFrameDecoder, FailTestLengthFieldFrameSize) {
383 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
387 .addBack(LengthFieldBasedFrameDecoder(4, 10, 0, 0, 4))
388 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
389 ASSERT_EQ(nullptr, buf);
394 auto bufFrame = IOBuf::create(16);
395 bufFrame->append(16);
396 RWPrivateCursor c(bufFrame.get());
397 c.writeBE((uint32_t)12); // frame size
398 c.write((uint32_t)0); // nothing
399 c.write((uint32_t)0); // nothing
400 c.write((uint32_t)0); // nothing
402 IOBufQueue q(IOBufQueue::cacheChainLength());
404 q.append(std::move(bufFrame));
406 EXPECT_EQ(called, 1);
409 TEST(LengthFieldFrameDecoder, FailTestLengthFieldInitialBytes) {
410 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
414 .addBack(LengthFieldBasedFrameDecoder(4, 10, 0, 0, 10))
415 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
416 ASSERT_EQ(nullptr, buf);
421 auto bufFrame = IOBuf::create(16);
422 bufFrame->append(16);
423 RWPrivateCursor c(bufFrame.get());
424 c.writeBE((uint32_t)4); // frame size
425 c.write((uint32_t)0); // nothing
426 c.write((uint32_t)0); // nothing
427 c.write((uint32_t)0); // nothing
429 IOBufQueue q(IOBufQueue::cacheChainLength());
431 q.append(std::move(bufFrame));
433 EXPECT_EQ(called, 1);
436 TEST(LineBasedFrameDecoder, Simple) {
437 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
441 .addBack(LineBasedFrameDecoder(10))
442 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
443 auto sz = buf->computeChainDataLength();
449 auto buf = IOBuf::create(3);
452 IOBufQueue q(IOBufQueue::cacheChainLength());
454 q.append(std::move(buf));
456 EXPECT_EQ(called, 0);
458 buf = IOBuf::create(1);
460 RWPrivateCursor c(buf.get());
462 q.append(std::move(buf));
464 EXPECT_EQ(called, 1);
466 buf = IOBuf::create(4);
468 RWPrivateCursor c1(buf.get());
474 q.append(std::move(buf));
476 EXPECT_EQ(called, 1);
478 buf = IOBuf::create(1);
480 RWPrivateCursor c2(buf.get());
482 q.append(std::move(buf));
484 EXPECT_EQ(called, 2);
487 TEST(LineBasedFrameDecoder, SaveDelimiter) {
488 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
492 .addBack(LineBasedFrameDecoder(10, false))
493 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
494 auto sz = buf->computeChainDataLength();
500 auto buf = IOBuf::create(3);
503 IOBufQueue q(IOBufQueue::cacheChainLength());
505 q.append(std::move(buf));
507 EXPECT_EQ(called, 0);
509 buf = IOBuf::create(1);
511 RWPrivateCursor c(buf.get());
513 q.append(std::move(buf));
515 EXPECT_EQ(called, 1);
517 buf = IOBuf::create(3);
519 RWPrivateCursor c1(buf.get());
523 q.append(std::move(buf));
525 EXPECT_EQ(called, 1);
527 buf = IOBuf::create(1);
529 RWPrivateCursor c2(buf.get());
531 q.append(std::move(buf));
533 EXPECT_EQ(called, 2);
536 TEST(LineBasedFrameDecoder, Fail) {
537 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
541 .addBack(LineBasedFrameDecoder(10))
542 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
543 ASSERT_EQ(nullptr, buf);
548 auto buf = IOBuf::create(11);
551 IOBufQueue q(IOBufQueue::cacheChainLength());
553 q.append(std::move(buf));
555 EXPECT_EQ(called, 1);
557 buf = IOBuf::create(1);
559 q.append(std::move(buf));
561 EXPECT_EQ(called, 1);
563 buf = IOBuf::create(2);
565 RWPrivateCursor c(buf.get());
568 q.append(std::move(buf));
570 EXPECT_EQ(called, 1);
572 buf = IOBuf::create(12);
574 RWPrivateCursor c2(buf.get());
575 for (int i = 0; i < 11; i++) {
578 c2.write<char>('\n');
579 q.append(std::move(buf));
581 EXPECT_EQ(called, 2);
584 TEST(LineBasedFrameDecoder, NewLineOnly) {
585 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
589 .addBack(LineBasedFrameDecoder(
590 10, true, LineBasedFrameDecoder::TerminatorType::NEWLINE))
591 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
592 auto sz = buf->computeChainDataLength();
598 auto buf = IOBuf::create(2);
600 RWPrivateCursor c(buf.get());
604 IOBufQueue q(IOBufQueue::cacheChainLength());
606 q.append(std::move(buf));
608 EXPECT_EQ(called, 1);
611 TEST(LineBasedFrameDecoder, CarriageNewLineOnly) {
612 Pipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
616 .addBack(LineBasedFrameDecoder(
617 10, true, LineBasedFrameDecoder::TerminatorType::CARRIAGENEWLINE))
618 .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
619 auto sz = buf->computeChainDataLength();
625 auto buf = IOBuf::create(3);
627 RWPrivateCursor c(buf.get());
632 IOBufQueue q(IOBufQueue::cacheChainLength());
634 q.append(std::move(buf));
636 EXPECT_EQ(called, 1);