Index: net/spdy/spdy_framer_test.cc |
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc |
index 30db38db5d3ebd0538f1431d59252f7b74bd0f3d..739d8085f8cf8c0e600d2e11220d2847b5eb8d53 100644 |
--- a/net/spdy/spdy_framer_test.cc |
+++ b/net/spdy/spdy_framer_test.cc |
@@ -1535,6 +1535,39 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
} |
{ |
+ const char kDescription[] = "'hello' data frame with padding, no FIN"; |
+ const unsigned char kV3FrameData[] = { // Also applies for V2. |
+ 0x00, 0x00, 0x00, 0x01, |
+ 0x00, 0x00, 0x00, 0x05, |
+ 'h', 'e', 'l', 'l', |
+ 'o' |
+ }; |
+ |
+ const unsigned char kV4FrameData[] = { |
+ 0x00, 0x15, 0x00, 0x10, // Length = 13. PAD_LOW set. |
+ 0x00, 0x00, 0x00, 0x01, |
+ 0x07, // Pad Low field. |
+ 'h', 'e', 'l', 'l', // Data |
+ 'o', |
+ '0', '0', '0', '0', // Padding |
+ '0', '0', '0' |
+ }; |
+ const char bytes[] = "hello"; |
+ |
+ SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes))); |
+ // 7 zeros and the pad low field make the overal padding to be 8 bytes. |
+ data_ir.set_padding_len(8); |
+ scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
+ if (IsSpdy4()) { |
+ CompareFrame( |
+ kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
+ } else { |
+ CompareFrame( |
+ kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); |
+ } |
+ } |
+ |
+ { |
const char kDescription[] = "Data frame with negative data byte, no FIN"; |
const unsigned char kV3FrameData[] = { // Also applies for V2. |
0x00, 0x00, 0x00, 0x01, |
@@ -3290,6 +3323,75 @@ TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) { |
EXPECT_EQ(1, visitor.settings_ack_received_); |
} |
+ |
+TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) { |
+ if (spdy_version_ < 4) { |
+ return; |
+ } |
+ |
+ const int kPaddingLen = 512; // So we get two bytes for padding length field. |
+ const char data_payload[] = "hello"; |
+ |
+ testing::StrictMock<test::MockSpdyFramerVisitor> visitor; |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ |
+ SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload))); |
+ data_ir.set_padding_len(kPaddingLen); |
+ scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
+ ASSERT_TRUE(frame.get() != NULL); |
+ |
+ int bytes_consumed = 0; |
+ |
+ // Send the frame header. |
+ EXPECT_CALL(visitor, OnDataFrameHeader(1, |
+ kPaddingLen + strlen(data_payload), |
+ false)); |
+ CHECK_EQ(8u, framer.ProcessInput(frame->data(), 8)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+ bytes_consumed += 8; |
+ |
+ // Send the first byte of the padding length field. |
+ CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+ bytes_consumed += 1; |
+ |
+ // Send the second byte of the padding length field. |
+ CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+ bytes_consumed += 1; |
+ |
+ // Send the first two bytes of the data payload. |
+ EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false)); |
+ CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+ bytes_consumed += 2; |
+ |
+ // Send the rest three bytes of the data payload. |
+ EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false)); |
+ CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+ bytes_consumed += 3; |
+ |
+ // Send the first 100 bytes of the padding payload. |
+ EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false)); |
+ CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+ bytes_consumed += 100; |
+ |
+ // Send rest of the padding payload. |
+ EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 410, false)); |
+ CHECK_EQ(412u, framer.ProcessInput(frame->data() + bytes_consumed, 412)); |
+ CHECK_EQ(framer.state(), SpdyFramer::SPDY_READING_COMMON_HEADER); |
+ CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR); |
+} |
+ |
TEST_P(SpdyFramerTest, ReadWindowUpdate) { |
SpdyFramer framer(spdy_version_); |
scoped_ptr<SpdyFrame> control_frame( |
@@ -3892,7 +3994,11 @@ TEST_P(SpdyFramerTest, CatchProbableHttpResponse) { |
} |
} |
-TEST_P(SpdyFramerTest, DataFrameFlags) { |
+TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { |
+ if (spdy_version_ >= 4) { |
+ return; |
+ } |
+ |
for (int flags = 0; flags < 256; ++flags) { |
SCOPED_TRACE(testing::Message() << "Flags " << flags); |
@@ -3928,6 +4034,55 @@ TEST_P(SpdyFramerTest, DataFrameFlags) { |
} |
} |
+TEST_P(SpdyFramerTest, DataFrameFlagsV4) { |
+ if (spdy_version_ < 4) { |
+ return; |
+ } |
+ |
+ uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | |
+ DATA_FLAG_PAD_LOW | DATA_FLAG_PAD_HIGH; |
+ |
+ for (int flags = 0; flags < 256; ++flags) { |
+ SCOPED_TRACE(testing::Message() << "Flags " << flags); |
+ |
+ testing::StrictMock<test::MockSpdyFramerVisitor> visitor; |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ |
+ net::SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
+ scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
+ SetFrameFlags(frame.get(), flags, spdy_version_); |
+ |
+ if (flags & ~valid_data_flags) { |
+ EXPECT_CALL(visitor, OnError(_)); |
+ } else { |
+ EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN)); |
+ if ((flags & DATA_FLAG_PAD_LOW) || (flags & DATA_FLAG_PAD_HIGH)) { |
+ // Expect Error since we don't set pad_high and pad_low in payload. |
+ EXPECT_CALL(visitor, OnError(_)); |
+ } else { |
+ EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false)); |
+ if (flags & DATA_FLAG_FIN) { |
+ EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)); |
+ } |
+ } |
+ } |
+ |
+ framer.ProcessInput(frame->data(), frame->size()); |
+ if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PAD_LOW) || |
+ (flags & DATA_FLAG_PAD_HIGH)) { |
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, |
+ framer.error_code()) |
+ << SpdyFramer::ErrorCodeToString(framer.error_code()); |
+ } else { |
+ EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
+ << SpdyFramer::ErrorCodeToString(framer.error_code()); |
+ } |
+ } |
+} |
+ |
TEST_P(SpdyFramerTest, SynStreamFrameFlags) { |
for (int flags = 0; flags < 256; ++flags) { |
SCOPED_TRACE(testing::Message() << "Flags " << flags); |