Index: net/spdy/spdy_framer_test.cc |
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc |
index 039f4de87093b7ed6bfd315f5d838cb68b326be1..8542835b67fdc00e256998568be205f6c14f5de7 100644 |
--- a/net/spdy/spdy_framer_test.cc |
+++ b/net/spdy/spdy_framer_test.cc |
@@ -11,6 +11,7 @@ |
#include "net/spdy/hpack_output_stream.h" |
#include "net/spdy/mock_spdy_framer_visitor.h" |
#include "net/spdy/spdy_frame_builder.h" |
+#include "net/spdy/spdy_frame_reader.h" |
#include "net/spdy/spdy_framer.h" |
#include "net/spdy/spdy_protocol.h" |
#include "net/spdy/spdy_test_utils.h" |
@@ -221,6 +222,8 @@ class SpdyFramerTestUtil { |
class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
public SpdyFramerDebugVisitorInterface { |
public: |
+ // This is larger than our max frame size because header blocks that |
+ // are too long can spill over into CONTINUATION frames. |
static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024; |
explicit TestSpdyVisitor(SpdyMajorVersion version) |
@@ -230,6 +233,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
syn_frame_count_(0), |
syn_reply_frame_count_(0), |
headers_frame_count_(0), |
+ push_promise_frame_count_(0), |
goaway_count_(0), |
setting_count_(0), |
settings_ack_sent_(0), |
@@ -260,13 +264,13 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
virtual void OnError(SpdyFramer* f) OVERRIDE { |
LOG(INFO) << "SpdyFramer Error: " |
<< SpdyFramer::ErrorCodeToString(f->error_code()); |
- error_count_++; |
+ ++error_count_; |
} |
virtual void OnDataFrameHeader(SpdyStreamId stream_id, |
size_t length, |
bool fin) OVERRIDE { |
- data_frame_count_++; |
+ ++data_frame_count_; |
header_stream_id_ = stream_id; |
} |
@@ -300,7 +304,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
CHECK(header_buffer_valid_); |
size_t parsed_length = framer_.ParseHeaderBlockInBuffer( |
header_buffer_.get(), header_buffer_length_, &headers_); |
- DCHECK_EQ(header_buffer_length_, parsed_length); |
+ LOG_IF(DFATAL, header_buffer_length_ != parsed_length) |
+ << "Check failed: header_buffer_length_ == parsed_length " |
+ << "(" << header_buffer_length_ << " vs. " << parsed_length << ")"; |
return true; |
} |
const size_t available = header_buffer_size_ - header_buffer_length_; |
@@ -318,24 +324,24 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
SpdyPriority priority, |
bool fin, |
bool unidirectional) OVERRIDE { |
- syn_frame_count_++; |
+ ++syn_frame_count_; |
InitHeaderStreaming(SYN_STREAM, stream_id); |
if (fin) { |
- fin_flag_count_++; |
+ ++fin_flag_count_; |
} |
} |
virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE { |
- syn_reply_frame_count_++; |
+ ++syn_reply_frame_count_; |
InitHeaderStreaming(SYN_REPLY, stream_id); |
if (fin) { |
- fin_flag_count_++; |
+ ++fin_flag_count_; |
} |
} |
virtual void OnRstStream(SpdyStreamId stream_id, |
SpdyRstStreamStatus status) OVERRIDE { |
- fin_frame_count_++; |
+ ++fin_frame_count_; |
} |
virtual bool OnRstStreamFrameData(const char* rst_stream_data, |
@@ -349,17 +355,17 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
virtual void OnSetting(SpdySettingsIds id, |
uint8 flags, |
uint32 value) OVERRIDE { |
- setting_count_++; |
+ ++setting_count_; |
} |
virtual void OnSettingsAck() OVERRIDE { |
- DCHECK_GE(4, framer_.protocol_version()); |
- settings_ack_received_++; |
+ DCHECK_LT(SPDY3, framer_.protocol_version()); |
+ ++settings_ack_received_; |
} |
virtual void OnSettingsEnd() OVERRIDE { |
- if (framer_.protocol_version() < 4) { return; } |
- settings_ack_sent_++; |
+ if (framer_.protocol_version() <= SPDY3) { return; } |
+ ++settings_ack_sent_; |
} |
virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE { |
@@ -368,14 +374,14 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, |
SpdyGoAwayStatus status) OVERRIDE { |
- goaway_count_++; |
+ ++goaway_count_; |
} |
virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE { |
- headers_frame_count_++; |
+ ++headers_frame_count_; |
InitHeaderStreaming(HEADERS, stream_id); |
if (fin) { |
- fin_flag_count_++; |
+ ++fin_flag_count_; |
} |
} |
@@ -388,13 +394,14 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
virtual void OnPushPromise(SpdyStreamId stream_id, |
SpdyStreamId promised_stream_id, |
bool end) OVERRIDE { |
+ ++push_promise_frame_count_; |
InitHeaderStreaming(PUSH_PROMISE, stream_id); |
last_push_promise_stream_ = stream_id; |
last_push_promise_promised_stream_ = promised_stream_id; |
} |
virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE { |
- continuation_count_++; |
+ ++continuation_count_; |
} |
virtual void OnSendCompressedFrame(SpdyStreamId stream_id, |
@@ -461,6 +468,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
int syn_frame_count_; |
int syn_reply_frame_count_; |
int headers_frame_count_; |
+ int push_promise_frame_count_; |
int goaway_count_; |
int setting_count_; |
int settings_ack_sent_; |
@@ -492,12 +500,39 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
SpdyHeaderBlock headers_; |
}; |
-// Retrieves serialized headers from SYN_STREAM frame. |
-// Does not check that the given frame is a SYN_STREAM. |
+// Retrieves serialized headers from a HEADERS or SYN_STREAM frame. |
base::StringPiece GetSerializedHeaders(const SpdyFrame* frame, |
const SpdyFramer& framer) { |
- return base::StringPiece(frame->data() + framer.GetSynStreamMinimumSize(), |
- frame->size() - framer.GetSynStreamMinimumSize()); |
+ SpdyFrameReader reader(frame->data(), frame->size()); |
+ reader.Seek(2); // Seek past the frame length. |
+ SpdyFrameType frame_type; |
+ if (framer.protocol_version() > SPDY3) { |
+ uint8 serialized_type; |
+ reader.ReadUInt8(&serialized_type); |
+ frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(), |
+ serialized_type); |
+ DCHECK_EQ(HEADERS, frame_type); |
+ uint8 flags; |
+ reader.ReadUInt8(&flags); |
+ if (flags & HEADERS_FLAG_PRIORITY) { |
+ frame_type = SYN_STREAM; |
+ } |
+ } else { |
+ uint16 serialized_type; |
+ reader.ReadUInt16(&serialized_type); |
+ frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(), |
+ serialized_type); |
+ DCHECK(frame_type == HEADERS || |
+ frame_type == SYN_STREAM) << frame_type; |
+ } |
+ |
+ if (frame_type == SYN_STREAM) { |
+ return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(), |
+ frame->size() - framer.GetSynStreamMinimumSize()); |
+ } else { |
+ return StringPiece(frame->data() + framer.GetHeadersMinimumSize(), |
+ frame->size() - framer.GetHeadersMinimumSize()); |
+ } |
} |
} // namespace test |
@@ -517,7 +552,8 @@ class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> { |
protected: |
virtual void SetUp() { |
spdy_version_ = GetParam(); |
- spdy_version_ch_ = static_cast<unsigned char>(spdy_version_); |
+ spdy_version_ch_ = static_cast<unsigned char>( |
+ SpdyConstants::SerializeMajorVersion(spdy_version_)); |
} |
void CompareFrame(const string& description, |
@@ -673,7 +709,7 @@ TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) { |
// Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an |
// error (but don't crash). |
TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) { |
- if (spdy_version_ < SPDY4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -698,7 +734,7 @@ TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) { |
// Test that if we receive a PUSH_PROMISE with promised stream ID zero, we |
// signal an error (but don't crash). |
TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) { |
- if (spdy_version_ < SPDY4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -721,7 +757,7 @@ TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) { |
} |
TEST_P(SpdyFramerTest, DuplicateHeader) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
// TODO(jgraettinger): Punting on this because we haven't determined |
// whether duplicate HPACK headers other than Cookie are an error. |
// If they are, this will need to be updated to use HpackOutputStream. |
@@ -729,14 +765,14 @@ TEST_P(SpdyFramerTest, DuplicateHeader) { |
} |
SpdyFramer framer(spdy_version_); |
// Frame builder with plentiful buffer size. |
- SpdyFrameBuilder frame(1024); |
- if (spdy_version_ < 4) { |
+ SpdyFrameBuilder frame(1024, spdy_version_); |
+ if (spdy_version_ <= SPDY3) { |
frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE); |
frame.WriteUInt32(3); // stream_id |
frame.WriteUInt32(0); // associated stream id |
frame.WriteUInt16(0); // Priority. |
} else { |
- frame.WriteFramePrefix(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3); |
+ frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3); |
frame.WriteUInt32(framer.GetHighestPriority()); |
} |
@@ -770,17 +806,17 @@ TEST_P(SpdyFramerTest, DuplicateHeader) { |
TEST_P(SpdyFramerTest, MultiValueHeader) { |
SpdyFramer framer(spdy_version_); |
// Frame builder with plentiful buffer size. |
- SpdyFrameBuilder frame(1024); |
- if (spdy_version_ < 4) { |
+ SpdyFrameBuilder frame(1024, spdy_version_); |
+ if (spdy_version_ <= SPDY3) { |
frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE); |
frame.WriteUInt32(3); // stream_id |
frame.WriteUInt32(0); // associated stream id |
frame.WriteUInt16(0); // Priority. |
} else { |
- frame.WriteFramePrefix(framer, |
- HEADERS, |
- HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, |
- 3); |
+ frame.BeginNewFrame(framer, |
+ HEADERS, |
+ HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, |
+ 3); |
frame.WriteUInt32(framer.GetHighestPriority()); |
} |
@@ -789,11 +825,13 @@ TEST_P(SpdyFramerTest, MultiValueHeader) { |
frame.WriteUInt16(1); // Number of headers. |
frame.WriteString("name"); |
frame.WriteString(value); |
- } else if (spdy_version_ >= 4) { |
- HpackOutputStream output_stream(1024); |
- output_stream.AppendLiteralHeaderNoIndexingWithName("name", value); |
+ } else if (spdy_version_ > SPDY3) { |
+ // TODO(jgraettinger): If this pattern appears again, move to test class. |
+ std::map<string, string> header_set; |
+ header_set["name"] = value; |
string buffer; |
- output_stream.TakeString(&buffer); |
+ HpackEncoder encoder(ObtainHpackHuffmanTable()); |
+ encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer); |
frame.WriteBytes(&buffer[0], buffer.size()); |
} else { |
frame.WriteUInt32(1); // Number of headers. |
@@ -817,7 +855,7 @@ TEST_P(SpdyFramerTest, MultiValueHeader) { |
} |
TEST_P(SpdyFramerTest, BasicCompression) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
// Deflate compression doesn't apply to HPACK. |
return; |
} |
@@ -962,7 +1000,7 @@ TEST_P(SpdyFramerTest, Basic) { |
0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1 |
0x00, 0x00, 0x00, 0x08, |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL |
0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 |
0x00, 0x00, 0x00, 0x00, |
@@ -970,7 +1008,7 @@ TEST_P(SpdyFramerTest, Basic) { |
0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3 |
0x00, 0x00, 0x00, 0x08, |
0x00, 0x00, 0x00, 0x03, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL |
}; |
const unsigned char kV3Input[] = { |
@@ -1021,7 +1059,7 @@ TEST_P(SpdyFramerTest, Basic) { |
0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1 |
0x00, 0x00, 0x00, 0x08, |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL |
0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 |
0x00, 0x00, 0x00, 0x00, |
@@ -1029,7 +1067,7 @@ TEST_P(SpdyFramerTest, Basic) { |
0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3 |
0x00, 0x00, 0x00, 0x08, |
0x00, 0x00, 0x00, 0x03, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL |
}; |
// SYN_STREAM doesn't exist in SPDY4, so instead we send |
@@ -1066,14 +1104,14 @@ TEST_P(SpdyFramerTest, Basic) { |
0x00, 0x04, 0x03, 0x00, // RST_STREAM on Stream #1 |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x08, // RST_STREAM_CANCEL |
0x00, 0x00, 0x00, 0x00, // DATA on Stream #3 |
0x00, 0x00, 0x00, 0x03, |
0x00, 0x0f, 0x03, 0x00, // RST_STREAM on Stream #3 |
0x00, 0x00, 0x00, 0x03, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, 0x00, 0x08, // RST_STREAM_CANCEL |
0x52, 0x45, 0x53, 0x45, // opaque data |
0x54, 0x53, 0x54, 0x52, |
0x45, 0x41, 0x4d, |
@@ -1292,7 +1330,7 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) { |
} |
TEST_P(SpdyFramerTest, HeaderCompression) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
// Deflate compression doesn't apply to HPACK. |
return; |
} |
@@ -1376,7 +1414,7 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressors) { |
EXPECT_TRUE(syn_frame.get() != NULL); |
StringPiece bytes = "this is a test test test test test!"; |
- net::SpdyDataIR data_ir(1, bytes); |
+ SpdyDataIR data_ir(1, bytes); |
data_ir.set_fin(true); |
scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir)); |
EXPECT_TRUE(send_frame.get() != NULL); |
@@ -1420,7 +1458,7 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) { |
EXPECT_TRUE(syn_frame.get() != NULL); |
const char bytes[] = "this is a test test test test test!"; |
- net::SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes))); |
+ SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes))); |
data_ir.set_fin(true); |
scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir)); |
EXPECT_TRUE(send_frame.get() != NULL); |
@@ -1454,7 +1492,7 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) { |
TEST_P(SpdyFramerTest, WindowUpdateFrame) { |
SpdyFramer framer(spdy_version_); |
scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate( |
- net::SpdyWindowUpdateIR(1, 0x12345678))); |
+ SpdyWindowUpdateIR(1, 0x12345678))); |
const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678"; |
const unsigned char kV3FrameData[] = { // Also applies for V2. |
@@ -1507,7 +1545,69 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
SpdyDataIR data_header_ir(1); |
data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes))); |
- frame.reset(framer.SerializeDataFrameHeader(data_header_ir)); |
+ frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField( |
+ data_header_ir)); |
+ CompareCharArraysWithHexError( |
+ kDescription, |
+ reinterpret_cast<const unsigned char*>(frame->data()), |
+ framer.GetDataFrameMinimumSize(), |
+ IsSpdy4() ? kV4FrameData : kV3FrameData, |
+ framer.GetDataFrameMinimumSize()); |
+ } |
+ |
+ { |
+ const char kDescription[] = "'hello' data frame with more 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[] = { |
+ 0x01, 0x0b, 0x00, 0x30, // Length = 267. PAD_HIGH and PAD_LOW set. |
+ 0x00, 0x00, 0x00, 0x01, |
+ 0x01, 0x04, // Pad Low and Pad High fields. |
+ 'h', 'e', 'l', 'l', // Data |
+ 'o', |
+ // Padding of 260 zeros (so both PAD_HIGH and PAD_LOW fields are used). |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', |
+ }; |
+ const char bytes[] = "hello"; |
+ |
+ SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes))); |
+ // 260 zeros and the pad low/high fields make the overall padding to be 262 |
+ // bytes. |
+ data_ir.set_padding_len(262); |
+ scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
+ if (IsSpdy4()) { |
+ CompareFrame( |
+ kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
+ } else { |
+ CompareFrame( |
+ kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); |
+ } |
+ |
+ frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir)); |
CompareCharArraysWithHexError( |
kDescription, |
reinterpret_cast<const unsigned char*>(frame->data()), |
@@ -1517,7 +1617,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
} |
{ |
- const char kDescription[] = "'hello' data frame with padding, no FIN"; |
+ const char kDescription[] = "'hello' data frame with few padding, no FIN"; |
const unsigned char kV3FrameData[] = { // Also applies for V2. |
0x00, 0x00, 0x00, 0x01, |
0x00, 0x00, 0x00, 0x05, |
@@ -1537,7 +1637,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
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. |
+ // 7 zeros and the pad low field make the overall padding to be 8 bytes. |
data_ir.set_padding_len(8); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
if (IsSpdy4()) { |
@@ -1550,6 +1650,47 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
} |
{ |
+ const char kDescription[] = |
+ "'hello' data frame with 1 byte 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, 0x06, 0x00, 0x10, // Length = 6. PAD_LOW set. |
+ 0x00, 0x00, 0x00, 0x01, |
+ 0x00, // Pad Low field. |
+ 'h', 'e', 'l', 'l', // Data |
+ 'o', |
+ }; |
+ const char bytes[] = "hello"; |
+ |
+ SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes))); |
+ // The pad low field itself is used for the 1-byte padding and no padding |
+ // payload is needed. |
+ data_ir.set_padding_len(1); |
+ scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
+ if (IsSpdy4()) { |
+ CompareFrame( |
+ kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
+ } else { |
+ CompareFrame( |
+ kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); |
+ } |
+ |
+ frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir)); |
+ CompareCharArraysWithHexError( |
+ kDescription, |
+ reinterpret_cast<const unsigned char*>(frame->data()), |
+ framer.GetDataFrameMinimumSize(), |
+ IsSpdy4() ? kV4FrameData : kV3FrameData, |
+ framer.GetDataFrameMinimumSize()); |
+ } |
+ |
+ { |
const char kDescription[] = "Data frame with negative data byte, no FIN"; |
const unsigned char kV3FrameData[] = { // Also applies for V2. |
0x00, 0x00, 0x00, 0x01, |
@@ -1561,7 +1702,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
0x00, 0x00, 0x00, 0x01, |
0xff |
}; |
- net::SpdyDataIR data_ir(1, StringPiece("\xff", 1)); |
+ SpdyDataIR data_ir(1, StringPiece("\xff", 1)); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
if (IsSpdy4()) { |
CompareFrame( |
@@ -1586,7 +1727,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
'h', 'e', 'l', 'l', |
'o' |
}; |
- net::SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
+ SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
data_ir.set_fin(true); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
if (IsSpdy4()) { |
@@ -1608,7 +1749,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x01, |
}; |
- net::SpdyDataIR data_ir(1, StringPiece()); |
+ SpdyDataIR data_ir(1, StringPiece()); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
if (IsSpdy4()) { |
CompareFrame( |
@@ -1617,6 +1758,14 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
CompareFrame( |
kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); |
} |
+ |
+ frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir)); |
+ CompareCharArraysWithHexError( |
+ kDescription, |
+ reinterpret_cast<const unsigned char*>(frame->data()), |
+ framer.GetDataFrameMinimumSize(), |
+ IsSpdy4() ? kV4FrameData : kV3FrameData, |
+ framer.GetDataFrameMinimumSize()); |
} |
{ |
@@ -1633,7 +1782,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
'h', 'e', 'l', 'l', |
'o' |
}; |
- net::SpdyDataIR data_ir(0x7fffffff, "hello"); |
+ SpdyDataIR data_ir(0x7fffffff, "hello"); |
data_ir.set_fin(true); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
if (IsSpdy4()) { |
@@ -1662,7 +1811,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) { |
memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader)); |
memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize); |
- net::SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size())); |
+ SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size())); |
data_ir.set_fin(true); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize); |
@@ -2136,7 +2285,7 @@ TEST_P(SpdyFramerTest, CreateRstStream) { |
0x00, 0x00, 0x00, 0x01, |
0x52, 0x53, 0x54 |
}; |
- net::SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST"); |
+ SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST"); |
scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream)); |
if (IsSpdy4()) { |
CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
@@ -2158,9 +2307,9 @@ TEST_P(SpdyFramerTest, CreateRstStream) { |
0x7f, 0xff, 0xff, 0xff, |
0x00, 0x00, 0x00, 0x01, |
}; |
- net::SpdyRstStreamIR rst_stream(0x7FFFFFFF, |
- RST_STREAM_PROTOCOL_ERROR, |
- ""); |
+ SpdyRstStreamIR rst_stream(0x7FFFFFFF, |
+ RST_STREAM_PROTOCOL_ERROR, |
+ ""); |
scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream)); |
if (IsSpdy4()) { |
CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
@@ -2182,9 +2331,9 @@ TEST_P(SpdyFramerTest, CreateRstStream) { |
0x7f, 0xff, 0xff, 0xff, |
0x00, 0x00, 0x00, 0x06, |
}; |
- net::SpdyRstStreamIR rst_stream(0x7FFFFFFF, |
- RST_STREAM_INTERNAL_ERROR, |
- ""); |
+ SpdyRstStreamIR rst_stream(0x7FFFFFFF, |
+ RST_STREAM_INTERNAL_ERROR, |
+ ""); |
scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream)); |
if (IsSpdy4()) { |
CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
@@ -2680,7 +2829,7 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) { |
0x00, 0x00, 0x00, 0x01, |
}; |
scoped_ptr<SpdyFrame> frame( |
- framer.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 1))); |
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1))); |
if (IsSpdy4()) { |
CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
} else { |
@@ -2702,7 +2851,7 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) { |
0x00, 0x00, 0x00, 0x01, |
}; |
scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate( |
- net::SpdyWindowUpdateIR(0x7FFFFFFF, 1))); |
+ SpdyWindowUpdateIR(0x7FFFFFFF, 1))); |
if (IsSpdy4()) { |
CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
} else { |
@@ -2724,7 +2873,7 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) { |
0x7f, 0xff, 0xff, 0xff, |
}; |
scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate( |
- net::SpdyWindowUpdateIR(1, 0x7FFFFFFF))); |
+ SpdyWindowUpdateIR(1, 0x7FFFFFFF))); |
if (IsSpdy4()) { |
CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); |
} else { |
@@ -2769,13 +2918,13 @@ TEST_P(SpdyFramerTest, CreateBlocked) { |
CompareFrames(kDescription, *frame_serialized, *frame_created); |
} |
-TEST_P(SpdyFramerTest, CreatePushPromise) { |
+TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) { |
if (spdy_version_ < SPDY4) { |
return; |
} |
SpdyFramer framer(spdy_version_); |
- |
+ framer.set_enable_compression(false); |
const char kDescription[] = "PUSH_PROMISE frame"; |
const unsigned char kFrameData[] = { |
@@ -2888,7 +3037,7 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) { |
} |
TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
// TODO(jgraettinger): This test setup doesn't work with HPACK. |
return; |
} |
@@ -2923,7 +3072,7 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) { |
} |
TEST_P(SpdyFramerTest, ControlFrameTooLarge) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
// TODO(jgraettinger): This test setup doesn't work with HPACK. |
return; |
} |
@@ -2963,6 +3112,63 @@ TEST_P(SpdyFramerTest, ControlFrameTooLarge) { |
EXPECT_EQ(0u, visitor.header_buffer_length_); |
} |
+TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_enable_compression(false); |
+ SpdyHeadersIR headers(1); |
+ |
+ // Exact payload length will change with HPACK, but this should be long |
+ // enough to cause an overflow. |
+ const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize(); |
+ string big_value(kBigValueSize, 'x'); |
+ headers.SetHeader("aa", big_value.c_str()); |
+ scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers)); |
+ EXPECT_TRUE(control_frame.get() != NULL); |
+ EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize()); |
+ |
+ TestSpdyVisitor visitor(spdy_version_); |
+ visitor.SimulateInFramer( |
+ reinterpret_cast<unsigned char*>(control_frame->data()), |
+ control_frame->size()); |
+ EXPECT_TRUE(visitor.header_buffer_valid_); |
+ EXPECT_EQ(0, visitor.error_count_); |
+ EXPECT_EQ(1, visitor.headers_frame_count_); |
+ EXPECT_EQ(1, visitor.continuation_count_); |
+ EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); |
+} |
+ |
+TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_enable_compression(false); |
+ SpdyPushPromiseIR push_promise(1, 2); |
+ |
+ // Exact payload length will change with HPACK, but this should be long |
+ // enough to cause an overflow. |
+ const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize(); |
+ string big_value(kBigValueSize, 'x'); |
+ push_promise.SetHeader("aa", big_value.c_str()); |
+ scoped_ptr<SpdyFrame> control_frame( |
+ framer.SerializePushPromise(push_promise)); |
+ EXPECT_TRUE(control_frame.get() != NULL); |
+ EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize()); |
+ |
+ TestSpdyVisitor visitor(spdy_version_); |
+ visitor.SimulateInFramer( |
+ reinterpret_cast<unsigned char*>(control_frame->data()), |
+ control_frame->size()); |
+ EXPECT_TRUE(visitor.header_buffer_valid_); |
+ EXPECT_EQ(0, visitor.error_count_); |
+ EXPECT_EQ(1, visitor.push_promise_frame_count_); |
+ EXPECT_EQ(1, visitor.continuation_count_); |
+ EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); |
+} |
+ |
// Check that the framer stops delivering header data chunks once the visitor |
// declares it doesn't want any more. This is important to guard against |
// "zip bomb" types of attacks. |
@@ -3007,7 +3213,7 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) { |
} |
TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
// Deflate compression doesn't apply to HPACK. |
return; |
} |
@@ -3086,7 +3292,7 @@ TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) { |
visitor.SimulateInFramer( |
reinterpret_cast<unsigned char*>(control_frame->data()), |
framer.GetControlFrameHeaderSize()); |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
// Should generate an error, since zero-len settings frames are unsupported. |
EXPECT_EQ(1, visitor.error_count_); |
} else { |
@@ -3148,7 +3354,7 @@ TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) { |
control_frame->size()); |
EXPECT_EQ(0, visitor.error_count_); |
EXPECT_EQ(3, visitor.setting_count_); |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
EXPECT_EQ(1, visitor.settings_ack_sent_); |
} |
@@ -3166,7 +3372,7 @@ TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) { |
} |
EXPECT_EQ(0, visitor.error_count_); |
EXPECT_EQ(3 * 2, visitor.setting_count_); |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
EXPECT_EQ(2, visitor.settings_ack_sent_); |
} |
} |
@@ -3289,7 +3495,7 @@ TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) { |
} |
TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
SpdyFramer framer(spdy_version_); |
@@ -3310,7 +3516,7 @@ TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) { |
TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3380,7 +3586,7 @@ TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) { |
TEST_P(SpdyFramerTest, ReadWindowUpdate) { |
SpdyFramer framer(spdy_version_); |
scoped_ptr<SpdyFrame> control_frame( |
- framer.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 2))); |
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2))); |
TestSpdyVisitor visitor(spdy_version_); |
visitor.SimulateInFramer( |
reinterpret_cast<unsigned char*>(control_frame->data()), |
@@ -3444,7 +3650,7 @@ TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) { |
string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData), |
arraysize(kV3FrameData)); |
scoped_ptr<SpdyFrame> control_frame( |
- framer.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 2))); |
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2))); |
multiple_frame_data.append(string(control_frame->data(), |
control_frame->size())); |
visitor.SimulateInFramer( |
@@ -3455,13 +3661,13 @@ TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) { |
EXPECT_EQ(2u, visitor.last_window_update_delta_); |
} |
-TEST_P(SpdyFramerTest, CreateContinuation) { |
+TEST_P(SpdyFramerTest, CreateContinuationUncompressed) { |
if (spdy_version_ < SPDY4) { |
return; |
} |
SpdyFramer framer(spdy_version_); |
- |
+ framer.set_enable_compression(false); |
const char kDescription[] = "CONTINUATION frame"; |
const unsigned char kFrameData[] = { |
@@ -3483,7 +3689,7 @@ TEST_P(SpdyFramerTest, CreateContinuation) { |
} |
TEST_P(SpdyFramerTest, ReadCompressedPushPromise) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3506,7 +3712,7 @@ TEST_P(SpdyFramerTest, ReadCompressedPushPromise) { |
} |
TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3551,7 +3757,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) { |
} |
TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3597,7 +3803,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) { |
} |
TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3644,7 +3850,7 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) { |
} |
TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3680,7 +3886,7 @@ TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) { |
} |
TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3707,7 +3913,7 @@ TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) { |
} |
TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3740,7 +3946,7 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) { |
} |
TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -3933,7 +4139,7 @@ TEST_P(SpdyFramerTest, StatusCodeToStringTest) { |
EXPECT_STREQ("FLOW_CONTROL_ERROR", |
SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR)); |
EXPECT_STREQ("UNKNOWN_STATUS", |
- SpdyFramer::StatusCodeToString(RST_STREAM_NUM_STATUS_CODES)); |
+ SpdyFramer::StatusCodeToString(-1)); |
} |
TEST_P(SpdyFramerTest, FrameTypeToStringTest) { |
@@ -3997,7 +4203,7 @@ TEST_P(SpdyFramerTest, CatchProbableHttpResponse) { |
} |
TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { |
- if (spdy_version_ >= 4) { |
+ if (spdy_version_ > SPDY3) { |
return; |
} |
@@ -4008,7 +4214,7 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { |
SpdyFramer framer(spdy_version_); |
framer.set_visitor(&visitor); |
- net::SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
+ SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
SetFrameFlags(frame.get(), flags, spdy_version_); |
@@ -4037,7 +4243,7 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { |
} |
TEST_P(SpdyFramerTest, DataFrameFlagsV4) { |
- if (spdy_version_ < 4) { |
+ if (spdy_version_ <= SPDY3) { |
return; |
} |
@@ -4051,7 +4257,7 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) { |
SpdyFramer framer(spdy_version_); |
framer.set_visitor(&visitor); |
- net::SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
+ SpdyDataIR data_ir(1, StringPiece("hello", 5)); |
scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); |
SetFrameFlags(frame.get(), flags, spdy_version_); |
@@ -4210,7 +4416,7 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) { |
SpdyFramer framer(spdy_version_); |
framer.set_visitor(&visitor); |
- net::SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, ""); |
+ SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, ""); |
scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream)); |
SetFrameFlags(frame.get(), flags, spdy_version_); |
@@ -4235,7 +4441,7 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) { |
} |
TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) { |
- if (spdy_version_ >= 4) { return; } |
+ if (spdy_version_ > SPDY3) { return; } |
for (int flags = 0; flags < 256; ++flags) { |
SCOPED_TRACE(testing::Message() << "Flags " << flags); |
@@ -4276,7 +4482,7 @@ TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) { |
} |
TEST_P(SpdyFramerTest, SettingsFrameFlags) { |
- if (spdy_version_ < 4) { return; } |
+ if (spdy_version_ <= SPDY3) { return; } |
for (int flags = 0; flags < 256; ++flags) { |
SCOPED_TRACE(testing::Message() << "Flags " << flags); |
@@ -4422,7 +4628,7 @@ TEST_P(SpdyFramerTest, PingFrameFlags) { |
scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42))); |
SetFrameFlags(frame.get(), flags, spdy_version_); |
- if (spdy_version_ >= SPDY4 && |
+ if (spdy_version_ > SPDY3 && |
flags == PING_FLAG_ACK) { |
EXPECT_CALL(visitor, OnPing(42, true)); |
} else if (flags == 0) { |
@@ -4432,7 +4638,7 @@ TEST_P(SpdyFramerTest, PingFrameFlags) { |
} |
framer.ProcessInput(frame->data(), frame->size()); |
- if ((spdy_version_ >= SPDY4 && flags == PING_FLAG_ACK) || |
+ if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) || |
flags == 0) { |
EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
@@ -4455,7 +4661,7 @@ TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) { |
framer.set_visitor(&visitor); |
scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate( |
- net::SpdyWindowUpdateIR(4, 1024))); |
+ SpdyWindowUpdateIR(4, 1024))); |
SetFrameFlags(frame.get(), flags, spdy_version_); |
if (flags != 0) { |
@@ -4623,61 +4829,72 @@ TEST_P(SpdyFramerTest, SettingsFlagsAndId) { |
// Test handling of a RST_STREAM with out-of-bounds status codes. |
TEST_P(SpdyFramerTest, RstStreamStatusBounds) { |
- DCHECK_GE(0xff, RST_STREAM_NUM_STATUS_CODES); |
- |
+ const unsigned char kRstStreamStatusTooLow = 0x00; |
+ const unsigned char kRstStreamStatusTooHigh = 0xff; |
const unsigned char kV3RstStreamInvalid[] = { |
0x80, spdy_version_ch_, 0x00, 0x03, |
0x00, 0x00, 0x00, 0x08, |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, RST_STREAM_INVALID |
+ 0x00, 0x00, 0x00, kRstStreamStatusTooLow |
}; |
const unsigned char kV4RstStreamInvalid[] = { |
0x00, 0x04, 0x03, 0x00, |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, RST_STREAM_INVALID |
+ 0x00, 0x00, 0x00, kRstStreamStatusTooLow |
}; |
const unsigned char kV3RstStreamNumStatusCodes[] = { |
0x80, spdy_version_ch_, 0x00, 0x03, |
0x00, 0x00, 0x00, 0x08, |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES |
+ 0x00, 0x00, 0x00, kRstStreamStatusTooHigh |
}; |
const unsigned char kV4RstStreamNumStatusCodes[] = { |
0x00, 0x04, 0x03, 0x00, |
0x00, 0x00, 0x00, 0x01, |
- 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES |
+ 0x00, 0x00, 0x00, kRstStreamStatusTooHigh |
}; |
testing::StrictMock<test::MockSpdyFramerVisitor> visitor; |
SpdyFramer framer(spdy_version_); |
framer.set_visitor(&visitor); |
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID)); |
if (IsSpdy4()) { |
+ EXPECT_CALL(visitor, OnError(_)); |
framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid), |
arraysize(kV4RstStreamInvalid)); |
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code()) |
+ << SpdyFramer::ErrorCodeToString(framer.error_code()); |
} else { |
+ EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID)); |
framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid), |
arraysize(kV3RstStreamInvalid)); |
- } |
- EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
+ EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
<< SpdyFramer::ErrorCodeToString(framer.error_code()); |
+ } |
+ |
+ |
+ framer.Reset(); |
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID)); |
if (IsSpdy4()) { |
+ EXPECT_CALL(visitor, OnError(_)); |
framer.ProcessInput( |
reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes), |
arraysize(kV4RstStreamNumStatusCodes)); |
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code()) |
+ << SpdyFramer::ErrorCodeToString(framer.error_code()); |
} else { |
+ EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID)); |
framer.ProcessInput( |
reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes), |
arraysize(kV3RstStreamNumStatusCodes)); |
- } |
- EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
+ EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
<< SpdyFramer::ErrorCodeToString(framer.error_code()); |
+ } |
} |
// Tests handling of a GOAWAY frame with out-of-bounds stream ID. |