Index: net/spdy/spdy_framer_test.cc |
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc |
index 2a005bb946a6be1f56d64ed0ff4a7fb570576137..9c3ec4585805fdcf907f901413f116396d2eec99 100644 |
--- a/net/spdy/spdy_framer_test.cc |
+++ b/net/spdy/spdy_framer_test.cc |
@@ -239,6 +239,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
settings_ack_sent_(0), |
settings_ack_received_(0), |
continuation_count_(0), |
+ altsvc_count_(0), |
+ test_altsvc_ir_(0), |
last_window_update_stream_(0), |
last_window_update_delta_(0), |
last_push_promise_stream_(0), |
@@ -404,6 +406,23 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
++continuation_count_; |
} |
+ virtual void OnAltSvc(SpdyStreamId stream_id, |
+ uint32 max_age, |
+ uint16 port, |
+ StringPiece protocol_id, |
+ StringPiece host, |
+ StringPiece origin) OVERRIDE { |
+ test_altsvc_ir_.set_stream_id(stream_id); |
+ test_altsvc_ir_.set_max_age(max_age); |
+ test_altsvc_ir_.set_port(port); |
+ test_altsvc_ir_.set_protocol_id(protocol_id.as_string()); |
+ test_altsvc_ir_.set_host(host.as_string()); |
+ if (origin.length() > 0) { |
+ test_altsvc_ir_.set_origin(origin.as_string()); |
+ } |
+ ++altsvc_count_; |
+ } |
+ |
virtual void OnSendCompressedFrame(SpdyStreamId stream_id, |
SpdyFrameType type, |
size_t payload_len, |
@@ -474,6 +493,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
int settings_ack_sent_; |
int settings_ack_received_; |
int continuation_count_; |
+ int altsvc_count_; |
+ SpdyAltSvcIR test_altsvc_ir_; |
SpdyStreamId last_window_update_stream_; |
uint32 last_window_update_delta_; |
SpdyStreamId last_push_promise_stream_; |
@@ -607,6 +628,7 @@ class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> { |
bool IsSpdy2() { return spdy_version_ == SPDY2; } |
bool IsSpdy3() { return spdy_version_ == SPDY3; } |
bool IsSpdy4() { return spdy_version_ == SPDY4; } |
+ bool IsSpdy5() { return spdy_version_ == SPDY5; } |
// Version of SPDY protocol to be used. |
SpdyMajorVersion spdy_version_; |
@@ -2890,9 +2912,11 @@ TEST_P(SpdyFramerTest, SerializeBlocked) { |
SpdyFramer framer(spdy_version_); |
const char kDescription[] = "BLOCKED frame"; |
+ const char kType = static_cast<unsigned char>( |
+ SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED)); |
const unsigned char kFrameData[] = { |
- 0x00, 0x00, 0x0a, 0x00, |
- 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x00, kType, 0x00, |
+ 0x00, 0x00, 0x00, 0x00, |
}; |
SpdyBlockedIR blocked_ir(0); |
scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir)); |
@@ -2913,7 +2937,7 @@ TEST_P(SpdyFramerTest, CreateBlocked) { |
framer.SerializeBlocked(SpdyBlockedIR(kStreamId))); |
SpdyBlockedIR blocked_ir(kStreamId); |
scoped_ptr<SpdySerializedFrame> frame_created( |
- framer.SerializeFrame(blocked_ir)); |
+ framer.SerializeFrame(blocked_ir)); |
CompareFrames(kDescription, *frame_serialized, *frame_created); |
} |
@@ -2946,6 +2970,36 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) { |
CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); |
} |
+TEST_P(SpdyFramerTest, CreateAltSvc) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ |
+ SpdyFramer framer(spdy_version_); |
+ |
+ const char kDescription[] = "ALTSVC frame"; |
+ const char kType = static_cast<unsigned char>( |
+ SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC)); |
+ const unsigned char kFrameData[] = { |
+ 0x00, 0x17, kType, 0x00, |
+ 0x00, 0x00, 0x00, 0x03, |
+ 0x00, 0x00, 0x00, 0x05, |
+ 0x01, 0xbb, 0x00, 0x04, // Port = 443 |
+ 'p', 'i', 'd', '1', // Protocol-ID |
+ 0x04, 'h', 'o', 's', |
+ 't', 'o', 'r', 'i', |
+ 'g', 'i', 'n', |
+ }; |
+ SpdyAltSvcIR altsvc_ir(3); |
+ altsvc_ir.set_max_age(5); |
+ altsvc_ir.set_port(443); |
+ altsvc_ir.set_protocol_id("pid1"); |
+ altsvc_ir.set_host("host"); |
+ altsvc_ir.set_origin("origin"); |
+ scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir)); |
+ CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); |
+} |
+ |
TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) { |
SpdyFramer framer(spdy_version_); |
SpdySynStreamIR syn_stream(1); |
@@ -4028,7 +4082,7 @@ TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) { |
TEST_P(SpdyFramerTest, SizesTest) { |
SpdyFramer framer(spdy_version_); |
EXPECT_EQ(8u, framer.GetDataFrameMinimumSize()); |
- if (IsSpdy4()) { |
+ if (IsSpdy4() || IsSpdy5()) { |
EXPECT_EQ(8u, framer.GetSynReplyMinimumSize()); |
EXPECT_EQ(12u, framer.GetRstStreamMinimumSize()); |
EXPECT_EQ(8u, framer.GetSettingsMinimumSize()); |
@@ -4038,6 +4092,7 @@ TEST_P(SpdyFramerTest, SizesTest) { |
EXPECT_EQ(12u, framer.GetWindowUpdateSize()); |
EXPECT_EQ(8u, framer.GetBlockedSize()); |
EXPECT_EQ(12u, framer.GetPushPromiseMinimumSize()); |
+ EXPECT_EQ(17u, framer.GetAltSvcMinimumSize()); |
EXPECT_EQ(8u, framer.GetFrameMinimumSize()); |
EXPECT_EQ(16383u, framer.GetFrameMaximumSize()); |
EXPECT_EQ(16375u, framer.GetDataFrameMaximumPayload()); |
@@ -4085,9 +4140,12 @@ TEST_P(SpdyFramerTest, StateToStringTest) { |
EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD", |
SpdyFramer::StateToString( |
SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD)); |
+ EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD", |
+ SpdyFramer::StateToString( |
+ SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD)); |
EXPECT_STREQ("UNKNOWN_STATE", |
SpdyFramer::StateToString( |
- SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1)); |
+ SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1)); |
} |
TEST_P(SpdyFramerTest, ErrorCodeToStringTest) { |
@@ -4959,4 +5017,206 @@ TEST_P(SpdyFramerTest, OnBlocked) { |
<< SpdyFramer::ErrorCodeToString(framer.error_code()); |
} |
+TEST_P(SpdyFramerTest, OnAltSvc) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ |
+ const SpdyStreamId kStreamId = 1; |
+ |
+ testing::StrictMock<test::MockSpdyFramerVisitor> visitor; |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ |
+ EXPECT_CALL(visitor, OnAltSvc(kStreamId, |
+ 10, |
+ 443, |
+ StringPiece("pid"), |
+ StringPiece("h1"), |
+ StringPiece("o1"))); |
+ |
+ SpdyAltSvcIR altsvc_ir(1); |
+ altsvc_ir.set_max_age(10); |
+ altsvc_ir.set_port(443); |
+ altsvc_ir.set_protocol_id("pid"); |
+ altsvc_ir.set_host("h1"); |
+ altsvc_ir.set_origin("o1"); |
+ scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir)); |
+ framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() + |
+ altsvc_ir.protocol_id().length() + |
+ altsvc_ir.host().length() + |
+ altsvc_ir.origin().length()); |
+ |
+ EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
+ << SpdyFramer::ErrorCodeToString(framer.error_code()); |
+} |
+ |
+TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ |
+ const SpdyStreamId kStreamId = 1; |
+ |
+ testing::StrictMock<test::MockSpdyFramerVisitor> visitor; |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ |
+ EXPECT_CALL(visitor, OnAltSvc(kStreamId, |
+ 10, |
+ 443, |
+ StringPiece("pid"), |
+ StringPiece("h1"), |
+ StringPiece(""))); |
+ |
+ SpdyAltSvcIR altsvc_ir(1); |
+ altsvc_ir.set_max_age(10); |
+ altsvc_ir.set_port(443); |
+ altsvc_ir.set_protocol_id("pid"); |
+ altsvc_ir.set_host("h1"); |
+ scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir)); |
+ framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() + |
+ altsvc_ir.protocol_id().length() + |
+ altsvc_ir.host().length()); |
+ |
+ EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); |
+ EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) |
+ << SpdyFramer::ErrorCodeToString(framer.error_code()); |
+} |
+ |
+TEST_P(SpdyFramerTest, OnAltSvcBadLengths) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ |
+ const char kType = static_cast<unsigned char>( |
+ SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC)); |
+ { |
+ TestSpdyVisitor visitor(spdy_version_); |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ |
+ const unsigned char kFrameDataLargePIDLen[] = { |
+ 0x00, 0x17, kType, 0x00, |
+ 0x00, 0x00, 0x00, 0x03, |
+ 0x00, 0x00, 0x00, 0x05, |
+ 0x01, 0xbb, 0x00, 0x05, // Port = 443 |
+ 'p', 'i', 'd', '1', // Protocol-ID |
+ 0x04, 'h', 'o', 's', |
+ 't', 'o', 'r', 'i', |
+ 'g', 'i', 'n', |
+ }; |
+ |
+ visitor.SimulateInFramer(kFrameDataLargePIDLen, |
+ sizeof(kFrameDataLargePIDLen)); |
+ EXPECT_EQ(1, visitor.error_count_); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, |
+ visitor.framer_.error_code()); |
+ } |
+ |
+ { |
+ TestSpdyVisitor visitor(spdy_version_); |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ const unsigned char kFrameDataPIDLenLargerThanFrame[] = { |
+ 0x00, 0x17, kType, 0x00, |
+ 0x00, 0x00, 0x00, 0x03, |
+ 0x00, 0x00, 0x00, 0x05, |
+ 0x01, 0xbb, 0x00, 0x99, // Port = 443 |
+ 'p', 'i', 'd', '1', // Protocol-ID |
+ 0x04, 'h', 'o', 's', |
+ 't', 'o', 'r', 'i', |
+ 'g', 'i', 'n', |
+ }; |
+ |
+ visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame, |
+ sizeof(kFrameDataPIDLenLargerThanFrame)); |
+ EXPECT_EQ(1, visitor.error_count_); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, |
+ visitor.framer_.error_code()); |
+ } |
+ |
+ { |
+ TestSpdyVisitor visitor(spdy_version_); |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ |
+ const unsigned char kFrameDataLargeHostLen[] = { |
+ 0x00, 0x17, kType, 0x00, |
+ 0x00, 0x00, 0x00, 0x03, |
+ 0x00, 0x00, 0x00, 0x05, |
+ 0x01, 0xbb, 0x00, 0x04, // Port = 443 |
+ 'p', 'i', 'd', '1', // Protocol-ID |
+ 0x0f, 'h', 'o', 's', |
+ 't', 'o', 'r', 'i', |
+ 'g', 'i', 'n', |
+ }; |
+ |
+ visitor.SimulateInFramer(kFrameDataLargeHostLen, |
+ sizeof(kFrameDataLargeHostLen)); |
+ EXPECT_EQ(1, visitor.error_count_); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, |
+ visitor.framer_.error_code()); |
+ } |
+ |
+ { |
+ TestSpdyVisitor visitor(spdy_version_); |
+ SpdyFramer framer(spdy_version_); |
+ framer.set_visitor(&visitor); |
+ const unsigned char kFrameDataSmallPIDLen[] = { |
+ 0x00, 0x17, kType, 0x00, |
+ 0x00, 0x00, 0x00, 0x03, |
+ 0x00, 0x00, 0x00, 0x05, |
+ 0x01, 0xbb, 0x00, 0x01, // Port = 443 |
+ 'p', 'i', 'd', '1', // Protocol-ID |
+ 0x04, 'h', 'o', 's', |
+ 't', 'o', 'r', 'i', |
+ 'g', 'i', 'n', |
+ }; |
+ |
+ visitor.SimulateInFramer(kFrameDataSmallPIDLen, |
+ sizeof(kFrameDataSmallPIDLen)); |
+ EXPECT_EQ(1, visitor.error_count_); |
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, |
+ visitor.framer_.error_code()); |
+ } |
+} |
+ |
+// Tests handling of ALTSVC frames delivered in small chunks. |
+TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) { |
+ if (spdy_version_ < SPDY4) { |
+ return; |
+ } |
+ SpdyFramer framer(spdy_version_); |
+ SpdyAltSvcIR altsvc_ir(1); |
+ altsvc_ir.set_max_age(20); |
+ altsvc_ir.set_port(443); |
+ altsvc_ir.set_protocol_id("protocolid"); |
+ altsvc_ir.set_host("hostname"); |
+ |
+ scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir)); |
+ TestSpdyVisitor visitor(spdy_version_); |
+ visitor.use_compression_ = false; |
+ |
+ // Read data in small chunks. |
+ size_t framed_data = 0; |
+ size_t unframed_data = control_frame->size(); |
+ size_t kReadChunkSize = 5; // Read five bytes at a time. |
+ while (unframed_data > 0) { |
+ size_t to_read = min(kReadChunkSize, unframed_data); |
+ visitor.SimulateInFramer( |
+ reinterpret_cast<unsigned char*>(control_frame->data() + framed_data), |
+ to_read); |
+ unframed_data -= to_read; |
+ framed_data += to_read; |
+ } |
+ EXPECT_EQ(0, visitor.error_count_); |
+ EXPECT_EQ(1, visitor.altsvc_count_); |
+ EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age()); |
+ EXPECT_EQ(443u, visitor.test_altsvc_ir_.port()); |
+ EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id()); |
+ EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host()); |
+} |
+ |
} // namespace net |