test failure conditions in LengthFieldBasedFrameDecoder
authorDave Watson <davejwatson@fb.com>
Mon, 20 Apr 2015 17:34:01 +0000 (10:34 -0700)
committerAlecs King <int@fb.com>
Mon, 27 Apr 2015 23:47:28 +0000 (16:47 -0700)
Summary: Moar unittests.

Test Plan:
unittests

Reviewed By: hans@fb.com

Subscribers: doug, fugalh, folly-diffs@, jsedgwick, yfeldblum, chalfant

FB internal diff: D1959161

Signature: t1:1959161:1429292487:b7d10be35c2cf1d0bc1b399f4f523392a138a217

folly/wangle/codec/CodecTest.cpp
folly/wangle/codec/LengthFieldBasedFrameDecoder.cpp

index 7ba020435737b8aaad4700e0bee5150af2a43f0e..7657c715013596a42d25dc7f9599ad008a098a03 100644 (file)
@@ -16,9 +16,9 @@
 #include <gtest/gtest.h>
 
 #include <folly/wangle/codec/FixedLengthFrameDecoder.h>
-#include <folly/wangle/codec/LineBasedFrameDecoder.h>
 #include <folly/wangle/codec/LengthFieldBasedFrameDecoder.h>
 #include <folly/wangle/codec/LengthFieldPrepender.h>
+#include <folly/wangle/codec/LineBasedFrameDecoder.h>
 
 using namespace folly;
 using namespace folly::wangle;
@@ -54,7 +54,7 @@ class BytesReflector
   }
 };
 
-TEST(CodecTest, FixedLengthFrameDecoder) {
+TEST(FixedLengthFrameDecoder, FailWhenLengthFieldEndOffset) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -89,7 +89,7 @@ TEST(CodecTest, FixedLengthFrameDecoder) {
   EXPECT_EQ(called, 3);
 }
 
-TEST(CodecTest, LengthFieldFramePipeline) {
+TEST(LengthFieldFramePipeline, SimpleTest) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -110,7 +110,7 @@ TEST(CodecTest, LengthFieldFramePipeline) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFramePipelineLittleEndian) {
+TEST(LengthFieldFramePipeline, LittleEndian) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -131,7 +131,7 @@ TEST(CodecTest, LengthFieldFramePipelineLittleEndian) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderSimple) {
+TEST(LengthFieldFrameDecoder, Simple) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -162,7 +162,7 @@ TEST(CodecTest, LengthFieldFrameDecoderSimple) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderNoStrip) {
+TEST(LengthFieldFrameDecoder, NoStrip) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -193,7 +193,7 @@ TEST(CodecTest, LengthFieldFrameDecoderNoStrip) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderAdjustment) {
+TEST(LengthFieldFrameDecoder, Adjustment) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -224,7 +224,7 @@ TEST(CodecTest, LengthFieldFrameDecoderAdjustment) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderPreHeader) {
+TEST(LengthFieldFrameDecoder, PreHeader) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -256,7 +256,7 @@ TEST(CodecTest, LengthFieldFrameDecoderPreHeader) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderPostHeader) {
+TEST(LengthFieldFrameDecoder, PostHeader) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -288,7 +288,7 @@ TEST(CodecTest, LengthFieldFrameDecoderPostHeader) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderStripPrePostHeader) {
+TEST(LengthFieldFrameDecoderStrip, PrePostHeader) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -321,7 +321,7 @@ TEST(CodecTest, LengthFieldFrameDecoderStripPrePostHeader) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LengthFieldFrameDecoderStripPrePostHeaderFrameInclHeader) {
+TEST(LengthFieldFrameDecoder, StripPrePostHeaderFrameInclHeader) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -354,7 +354,86 @@ TEST(CodecTest, LengthFieldFrameDecoderStripPrePostHeaderFrameInclHeader) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LineBasedFrameDecoder) {
+TEST(LengthFieldFrameDecoder, FailTestLengthFieldEndOffset) {
+  ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
+  int called = 0;
+
+  pipeline
+    .addBack(LengthFieldBasedFrameDecoder(4, 10, 4, -2, 4))
+    .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
+        ASSERT_EQ(nullptr, buf);
+        called++;
+      }))
+    .finalize();
+
+  auto bufFrame = IOBuf::create(8);
+  bufFrame->append(8);
+  RWPrivateCursor c(bufFrame.get());
+  c.writeBE((uint32_t)0); // frame size
+  c.write((uint32_t)0); // crap
+
+  IOBufQueue q(IOBufQueue::cacheChainLength());
+
+  q.append(std::move(bufFrame));
+  pipeline.read(q);
+  EXPECT_EQ(called, 1);
+}
+
+TEST(LengthFieldFrameDecoder, FailTestLengthFieldFrameSize) {
+  ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
+  int called = 0;
+
+  pipeline
+    .addBack(LengthFieldBasedFrameDecoder(4, 10, 0, 0, 4))
+    .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
+        ASSERT_EQ(nullptr, buf);
+        called++;
+      }))
+    .finalize();
+
+  auto bufFrame = IOBuf::create(16);
+  bufFrame->append(16);
+  RWPrivateCursor c(bufFrame.get());
+  c.writeBE((uint32_t)12); // frame size
+  c.write((uint32_t)0); // nothing
+  c.write((uint32_t)0); // nothing
+  c.write((uint32_t)0); // nothing
+
+  IOBufQueue q(IOBufQueue::cacheChainLength());
+
+  q.append(std::move(bufFrame));
+  pipeline.read(q);
+  EXPECT_EQ(called, 1);
+}
+
+TEST(LengthFieldFrameDecoder, FailTestLengthFieldInitialBytes) {
+  ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
+  int called = 0;
+
+  pipeline
+    .addBack(LengthFieldBasedFrameDecoder(4, 10, 0, 0, 10))
+    .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
+        ASSERT_EQ(nullptr, buf);
+        called++;
+      }))
+    .finalize();
+
+  auto bufFrame = IOBuf::create(16);
+  bufFrame->append(16);
+  RWPrivateCursor c(bufFrame.get());
+  c.writeBE((uint32_t)4); // frame size
+  c.write((uint32_t)0); // nothing
+  c.write((uint32_t)0); // nothing
+  c.write((uint32_t)0); // nothing
+
+  IOBufQueue q(IOBufQueue::cacheChainLength());
+
+  q.append(std::move(bufFrame));
+  pipeline.read(q);
+  EXPECT_EQ(called, 1);
+}
+
+TEST(LineBasedFrameDecoder, Simple) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -405,7 +484,7 @@ TEST(CodecTest, LineBasedFrameDecoder) {
   EXPECT_EQ(called, 2);
 }
 
-TEST(CodecTest, LineBasedFrameDecoderSaveDelimiter) {
+TEST(LineBasedFrameDecoder, SaveDelimiter) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -454,13 +533,14 @@ TEST(CodecTest, LineBasedFrameDecoderSaveDelimiter) {
   EXPECT_EQ(called, 2);
 }
 
-TEST(CodecTest, LineBasedFrameDecoderFail) {
+TEST(LineBasedFrameDecoder, Fail) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
   pipeline
     .addBack(LineBasedFrameDecoder(10))
     .addBack(FrameTester([&](std::unique_ptr<IOBuf> buf) {
+        ASSERT_EQ(nullptr, buf);
         called++;
       }))
     .finalize();
@@ -501,7 +581,7 @@ TEST(CodecTest, LineBasedFrameDecoderFail) {
   EXPECT_EQ(called, 2);
 }
 
-TEST(CodecTest, LineBasedFrameDecoderNewLineOnly) {
+TEST(LineBasedFrameDecoder, NewLineOnly) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
@@ -528,7 +608,7 @@ TEST(CodecTest, LineBasedFrameDecoderNewLineOnly) {
   EXPECT_EQ(called, 1);
 }
 
-TEST(CodecTest, LineBasedFrameDecoderCarriageNewLineOnly) {
+TEST(LineBasedFrameDecoder, CarriageNewLineOnly) {
   ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> pipeline;
   int called = 0;
 
index 3bb12920360b213d0ba63c689ed9a6939eeccfcc..5fff70d5b89e4316620b48f44ed45e9b49d05808 100644 (file)
@@ -38,7 +38,7 @@ LengthFieldBasedFrameDecoder::LengthFieldBasedFrameDecoder(
 std::unique_ptr<IOBuf> LengthFieldBasedFrameDecoder::decode(
   Context* ctx, IOBufQueue& buf, size_t&) {
   // discarding too long frame
-  if (buf.chainLength() <= lengthFieldEndOffset_) {
+  if (buf.chainLength() < lengthFieldEndOffset_) {
     return nullptr;
   }
 
@@ -48,12 +48,18 @@ std::unique_ptr<IOBuf> LengthFieldBasedFrameDecoder::decode(
   frameLength += lengthAdjustment_ + lengthFieldEndOffset_;
 
   if (frameLength < lengthFieldEndOffset_) {
-    throw std::runtime_error("Frame too small");
+    buf.trimStart(lengthFieldEndOffset_);
+    ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
+                             "Frame too small"));
+    return nullptr;
   }
 
   if (frameLength > maxFrameLength_) {
-    throw std::runtime_error("Frame larger than " +
-                             folly::to<std::string>(maxFrameLength_));
+    buf.trimStart(frameLength);
+    ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
+                             "Frame larger than " +
+                             folly::to<std::string>(maxFrameLength_)));
+    return nullptr;
   }
 
   if (buf.chainLength() < frameLength) {
@@ -61,7 +67,10 @@ std::unique_ptr<IOBuf> LengthFieldBasedFrameDecoder::decode(
   }
 
   if (initialBytesToStrip_ > frameLength) {
-    throw std::runtime_error("InitialBytesToSkip larger than frame");
+    buf.trimStart(frameLength);
+    ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
+                             "InitialBytesToSkip larger than frame"));
+    return nullptr;
   }
 
   buf.trimStart(initialBytesToStrip_);