1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
21 using base::StringPiece
;
25 using std::numeric_limits
;
26 using testing::ElementsAre
;
34 static const size_t kMaxDecompressedSize
= 1024;
36 class MockDebugVisitor
: public SpdyFramerDebugVisitorInterface
{
38 MOCK_METHOD4(OnSendCompressedFrame
, void(SpdyStreamId stream_id
,
43 MOCK_METHOD3(OnReceiveCompressedFrame
, void(SpdyStreamId stream_id
,
48 class SpdyFramerTestUtil
{
50 // Decompress a single frame using the decompression context held by
51 // the SpdyFramer. The implemention is meant for use only in tests
52 // and will CHECK fail if the input is anything other than a single,
53 // well-formed compressed frame.
55 // Returns a new decompressed SpdyFrame.
56 template<class SpdyFrameType
> static SpdyFrame
* DecompressFrame(
57 SpdyFramer
* framer
, const SpdyFrameType
& frame
) {
58 DecompressionVisitor
visitor(framer
->protocol_version());
59 framer
->set_visitor(&visitor
);
60 CHECK_EQ(frame
.size(), framer
->ProcessInput(frame
.data(), frame
.size()));
61 CHECK_EQ(SpdyFramer::SPDY_RESET
, framer
->state());
62 framer
->set_visitor(NULL
);
64 char* buffer
= visitor
.ReleaseBuffer();
65 CHECK(buffer
!= NULL
);
66 SpdyFrame
* decompressed_frame
= new SpdyFrame(buffer
, visitor
.size(), true);
67 SetFrameLength(decompressed_frame
,
68 visitor
.size() - framer
->GetControlFrameHeaderSize(),
69 framer
->protocol_version());
70 return decompressed_frame
;
73 class DecompressionVisitor
: public SpdyFramerVisitorInterface
{
75 explicit DecompressionVisitor(SpdyMajorVersion version
)
76 : version_(version
), size_(0), finished_(false) {}
79 CHECK(buffer_
.get() == NULL
);
82 buffer_
.reset(new char[kMaxDecompressedSize
]);
85 virtual void OnError(SpdyFramer
* framer
) OVERRIDE
{ LOG(FATAL
); }
86 virtual void OnDataFrameHeader(SpdyStreamId stream_id
,
89 LOG(FATAL
) << "Unexpected data frame header";
91 virtual void OnStreamFrameData(SpdyStreamId stream_id
,
98 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
99 const char* header_data
,
100 size_t len
) OVERRIDE
{
101 CHECK(buffer_
.get() != NULL
);
102 CHECK_GE(kMaxDecompressedSize
, size_
+ len
);
105 memcpy(buffer_
.get() + size_
, header_data
, len
);
114 virtual void OnSynStream(SpdyStreamId stream_id
,
115 SpdyStreamId associated_stream_id
,
116 SpdyPriority priority
,
118 bool unidirectional
) OVERRIDE
{
119 SpdyFramer
framer(version_
);
120 framer
.set_enable_compression(false);
121 SpdySynStreamIR
syn_stream(stream_id
);
122 syn_stream
.set_associated_to_stream_id(associated_stream_id
);
123 syn_stream
.set_priority(priority
);
124 syn_stream
.set_fin(fin
);
125 syn_stream
.set_unidirectional(unidirectional
);
126 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
128 memcpy(buffer_
.get(), frame
->data(), framer
.GetSynStreamMinimumSize());
129 size_
+= framer
.GetSynStreamMinimumSize();
132 virtual void OnSynReply(SpdyStreamId stream_id
, bool fin
) OVERRIDE
{
133 SpdyFramer
framer(version_
);
134 framer
.set_enable_compression(false);
135 SpdyHeadersIR
headers(stream_id
);
136 headers
.set_fin(fin
);
137 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
139 memcpy(buffer_
.get(), frame
->data(), framer
.GetHeadersMinimumSize());
140 size_
+= framer
.GetSynStreamMinimumSize();
143 virtual void OnRstStream(SpdyStreamId stream_id
,
144 SpdyRstStreamStatus status
) OVERRIDE
{
147 virtual void OnSetting(SpdySettingsIds id
,
149 uint32 value
) OVERRIDE
{
152 virtual void OnPing(SpdyPingId unique_id
, bool is_ack
) OVERRIDE
{
155 virtual void OnSettingsEnd() OVERRIDE
{ LOG(FATAL
); }
156 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id
,
157 SpdyGoAwayStatus status
) OVERRIDE
{
161 virtual void OnHeaders(SpdyStreamId stream_id
,
164 SpdyFramer
framer(version_
);
165 framer
.set_enable_compression(false);
166 SpdyHeadersIR
headers(stream_id
);
167 headers
.set_fin(fin
);
168 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
170 memcpy(buffer_
.get(), frame
->data(), framer
.GetHeadersMinimumSize());
171 size_
+= framer
.GetHeadersMinimumSize();
174 virtual void OnWindowUpdate(SpdyStreamId stream_id
, int delta_window_size
) {
178 virtual void OnPushPromise(SpdyStreamId stream_id
,
179 SpdyStreamId promised_stream_id
,
181 SpdyFramer
framer(version_
);
182 framer
.set_enable_compression(false);
183 SpdyPushPromiseIR
push_promise(stream_id
, promised_stream_id
);
184 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePushPromise(push_promise
));
186 memcpy(buffer_
.get(), frame
->data(), framer
.GetPushPromiseMinimumSize());
187 size_
+= framer
.GetPushPromiseMinimumSize();
190 virtual void OnContinuation(SpdyStreamId stream_id
, bool end
) OVERRIDE
{
194 char* ReleaseBuffer() {
196 return buffer_
.release();
199 virtual void OnWindowUpdate(SpdyStreamId stream_id
,
200 uint32 delta_window_size
) OVERRIDE
{
204 size_t size() const {
210 SpdyMajorVersion version_
;
211 scoped_ptr
<char[]> buffer_
;
215 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor
);
219 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil
);
222 class TestSpdyVisitor
: public SpdyFramerVisitorInterface
,
223 public SpdyFramerDebugVisitorInterface
{
225 // This is larger than our max frame size because header blocks that
226 // are too long can spill over into CONTINUATION frames.
227 static const size_t kDefaultHeaderBufferSize
= 16 * 1024 * 1024;
229 explicit TestSpdyVisitor(SpdyMajorVersion version
)
231 use_compression_(false),
234 syn_reply_frame_count_(0),
235 headers_frame_count_(0),
236 push_promise_frame_count_(0),
239 settings_ack_sent_(0),
240 settings_ack_received_(0),
241 continuation_count_(0),
244 last_window_update_stream_(0),
245 last_window_update_delta_(0),
246 last_push_promise_stream_(0),
247 last_push_promise_promised_stream_(0),
252 zero_length_data_frame_count_(0),
253 control_frame_header_data_count_(0),
254 zero_length_control_frame_header_data_count_(0),
255 data_frame_count_(0),
256 last_payload_len_(0),
258 header_buffer_(new char[kDefaultHeaderBufferSize
]),
259 header_buffer_length_(0),
260 header_buffer_size_(kDefaultHeaderBufferSize
),
261 header_stream_id_(-1),
262 header_control_type_(DATA
),
263 header_buffer_valid_(false) {
266 virtual void OnError(SpdyFramer
* f
) OVERRIDE
{
267 LOG(INFO
) << "SpdyFramer Error: "
268 << SpdyFramer::ErrorCodeToString(f
->error_code());
272 virtual void OnDataFrameHeader(SpdyStreamId stream_id
,
276 header_stream_id_
= stream_id
;
279 virtual void OnStreamFrameData(SpdyStreamId stream_id
,
283 EXPECT_EQ(header_stream_id_
, stream_id
);
285 ++zero_length_data_frame_count_
;
288 std::cerr
<< "OnStreamFrameData(" << stream_id
<< ", \"";
290 for (size_t i
= 0 ; i
< len
; ++i
) {
291 std::cerr
<< std::hex
<< (0xFF & (unsigned int)data
[i
]) << std::dec
;
294 std::cerr
<< "\", " << len
<< ")\n";
297 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
298 const char* header_data
,
299 size_t len
) OVERRIDE
{
300 ++control_frame_header_data_count_
;
301 CHECK_EQ(header_stream_id_
, stream_id
);
303 ++zero_length_control_frame_header_data_count_
;
304 // Indicates end-of-header-block.
306 CHECK(header_buffer_valid_
);
307 size_t parsed_length
= framer_
.ParseHeaderBlockInBuffer(
308 header_buffer_
.get(), header_buffer_length_
, &headers_
);
309 LOG_IF(DFATAL
, header_buffer_length_
!= parsed_length
)
310 << "Check failed: header_buffer_length_ == parsed_length "
311 << "(" << header_buffer_length_
<< " vs. " << parsed_length
<< ")";
314 const size_t available
= header_buffer_size_
- header_buffer_length_
;
315 if (len
> available
) {
316 header_buffer_valid_
= false;
319 memcpy(header_buffer_
.get() + header_buffer_length_
, header_data
, len
);
320 header_buffer_length_
+= len
;
324 virtual void OnSynStream(SpdyStreamId stream_id
,
325 SpdyStreamId associated_stream_id
,
326 SpdyPriority priority
,
328 bool unidirectional
) OVERRIDE
{
330 InitHeaderStreaming(SYN_STREAM
, stream_id
);
336 virtual void OnSynReply(SpdyStreamId stream_id
, bool fin
) OVERRIDE
{
337 ++syn_reply_frame_count_
;
338 InitHeaderStreaming(SYN_REPLY
, stream_id
);
344 virtual void OnRstStream(SpdyStreamId stream_id
,
345 SpdyRstStreamStatus status
) OVERRIDE
{
349 virtual bool OnRstStreamFrameData(const char* rst_stream_data
,
350 size_t len
) OVERRIDE
{
351 if ((rst_stream_data
!= NULL
) && (len
> 0)) {
352 fin_opaque_data_
+= std::string(rst_stream_data
, len
);
357 virtual void OnSetting(SpdySettingsIds id
,
359 uint32 value
) OVERRIDE
{
363 virtual void OnSettingsAck() OVERRIDE
{
364 DCHECK_LT(SPDY3
, framer_
.protocol_version());
365 ++settings_ack_received_
;
368 virtual void OnSettingsEnd() OVERRIDE
{
369 if (framer_
.protocol_version() <= SPDY3
) { return; }
370 ++settings_ack_sent_
;
373 virtual void OnPing(SpdyPingId unique_id
, bool is_ack
) OVERRIDE
{
377 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id
,
378 SpdyGoAwayStatus status
) OVERRIDE
{
382 virtual void OnHeaders(SpdyStreamId stream_id
, bool fin
, bool end
) OVERRIDE
{
383 ++headers_frame_count_
;
384 InitHeaderStreaming(HEADERS
, stream_id
);
390 virtual void OnWindowUpdate(SpdyStreamId stream_id
,
391 uint32 delta_window_size
) OVERRIDE
{
392 last_window_update_stream_
= stream_id
;
393 last_window_update_delta_
= delta_window_size
;
396 virtual void OnPushPromise(SpdyStreamId stream_id
,
397 SpdyStreamId promised_stream_id
,
399 ++push_promise_frame_count_
;
400 InitHeaderStreaming(PUSH_PROMISE
, stream_id
);
401 last_push_promise_stream_
= stream_id
;
402 last_push_promise_promised_stream_
= promised_stream_id
;
405 virtual void OnContinuation(SpdyStreamId stream_id
, bool end
) OVERRIDE
{
406 ++continuation_count_
;
409 virtual void OnAltSvc(SpdyStreamId stream_id
,
412 StringPiece protocol_id
,
414 StringPiece origin
) OVERRIDE
{
415 test_altsvc_ir_
.set_stream_id(stream_id
);
416 test_altsvc_ir_
.set_max_age(max_age
);
417 test_altsvc_ir_
.set_port(port
);
418 test_altsvc_ir_
.set_protocol_id(protocol_id
.as_string());
419 test_altsvc_ir_
.set_host(host
.as_string());
420 if (origin
.length() > 0) {
421 test_altsvc_ir_
.set_origin(origin
.as_string());
426 virtual void OnSendCompressedFrame(SpdyStreamId stream_id
,
429 size_t frame_len
) OVERRIDE
{
430 last_payload_len_
= payload_len
;
431 last_frame_len_
= frame_len
;
434 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id
,
436 size_t frame_len
) OVERRIDE
{
437 last_frame_len_
= frame_len
;
440 // Convenience function which runs a framer simulation with particular input.
441 void SimulateInFramer(const unsigned char* input
, size_t size
) {
442 framer_
.set_enable_compression(use_compression_
);
443 framer_
.set_visitor(this);
444 size_t input_remaining
= size
;
445 const char* input_ptr
= reinterpret_cast<const char*>(input
);
446 while (input_remaining
> 0 &&
447 framer_
.error_code() == SpdyFramer::SPDY_NO_ERROR
) {
448 // To make the tests more interesting, we feed random (amd small) chunks
449 // into the framer. This simulates getting strange-sized reads from
451 const size_t kMaxReadSize
= 32;
453 (rand() % min(input_remaining
, kMaxReadSize
)) + 1;
454 size_t bytes_processed
= framer_
.ProcessInput(input_ptr
, bytes_read
);
455 input_remaining
-= bytes_processed
;
456 input_ptr
+= bytes_processed
;
460 void InitHeaderStreaming(SpdyFrameType header_control_type
,
461 SpdyStreamId stream_id
) {
462 DCHECK_GE(header_control_type
, FIRST_CONTROL_TYPE
);
463 DCHECK_LE(header_control_type
, LAST_CONTROL_TYPE
);
464 memset(header_buffer_
.get(), 0, header_buffer_size_
);
465 header_buffer_length_
= 0;
466 header_stream_id_
= stream_id
;
467 header_control_type_
= header_control_type
;
468 header_buffer_valid_
= true;
469 DCHECK_NE(header_stream_id_
, SpdyFramer::kInvalidStream
);
472 // Override the default buffer size (16K). Call before using the framer!
473 void set_header_buffer_size(size_t header_buffer_size
) {
474 header_buffer_size_
= header_buffer_size
;
475 header_buffer_
.reset(new char[header_buffer_size
]);
478 static size_t header_data_chunk_max_size() {
479 return SpdyFramer::kHeaderDataChunkMaxSize
;
483 bool use_compression_
;
485 // Counters from the visitor callbacks.
487 int syn_frame_count_
;
488 int syn_reply_frame_count_
;
489 int headers_frame_count_
;
490 int push_promise_frame_count_
;
493 int settings_ack_sent_
;
494 int settings_ack_received_
;
495 int continuation_count_
;
497 SpdyAltSvcIR test_altsvc_ir_
;
498 SpdyStreamId last_window_update_stream_
;
499 uint32 last_window_update_delta_
;
500 SpdyStreamId last_push_promise_stream_
;
501 SpdyStreamId last_push_promise_promised_stream_
;
503 int fin_frame_count_
; // The count of RST_STREAM type frames received.
504 std::string fin_opaque_data_
;
505 int fin_flag_count_
; // The count of frames with the FIN flag set.
506 int zero_length_data_frame_count_
; // The count of zero-length data frames.
507 int control_frame_header_data_count_
; // The count of chunks received.
508 // The count of zero-length control frame header data chunks received.
509 int zero_length_control_frame_header_data_count_
;
510 int data_frame_count_
;
511 size_t last_payload_len_
;
512 size_t last_frame_len_
;
514 // Header block streaming state:
515 scoped_ptr
<char[]> header_buffer_
;
516 size_t header_buffer_length_
;
517 size_t header_buffer_size_
;
518 SpdyStreamId header_stream_id_
;
519 SpdyFrameType header_control_type_
;
520 bool header_buffer_valid_
;
521 SpdyHeaderBlock headers_
;
524 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
525 base::StringPiece
GetSerializedHeaders(const SpdyFrame
* frame
,
526 const SpdyFramer
& framer
) {
527 SpdyFrameReader
reader(frame
->data(), frame
->size());
528 reader
.Seek(2); // Seek past the frame length.
529 SpdyFrameType frame_type
;
530 if (framer
.protocol_version() > SPDY3
) {
531 uint8 serialized_type
;
532 reader
.ReadUInt8(&serialized_type
);
533 frame_type
= SpdyConstants::ParseFrameType(framer
.protocol_version(),
535 DCHECK_EQ(HEADERS
, frame_type
);
537 reader
.ReadUInt8(&flags
);
538 if (flags
& HEADERS_FLAG_PRIORITY
) {
539 frame_type
= SYN_STREAM
;
542 uint16 serialized_type
;
543 reader
.ReadUInt16(&serialized_type
);
544 frame_type
= SpdyConstants::ParseFrameType(framer
.protocol_version(),
546 DCHECK(frame_type
== HEADERS
||
547 frame_type
== SYN_STREAM
) << frame_type
;
550 if (frame_type
== SYN_STREAM
) {
551 return StringPiece(frame
->data() + framer
.GetSynStreamMinimumSize(),
552 frame
->size() - framer
.GetSynStreamMinimumSize());
554 return StringPiece(frame
->data() + framer
.GetHeadersMinimumSize(),
555 frame
->size() - framer
.GetHeadersMinimumSize());
563 using net::test::SetFrameLength
;
564 using net::test::SetFrameFlags
;
565 using net::test::CompareCharArraysWithHexError
;
566 using net::test::SpdyFramerTestUtil
;
567 using net::test::TestSpdyVisitor
;
568 using net::test::GetSerializedHeaders
;
572 class SpdyFramerTest
: public ::testing::TestWithParam
<SpdyMajorVersion
> {
574 virtual void SetUp() {
575 spdy_version_
= GetParam();
576 spdy_version_ch_
= static_cast<unsigned char>(
577 SpdyConstants::SerializeMajorVersion(spdy_version_
));
580 void CompareFrame(const string
& description
,
581 const SpdyFrame
& actual_frame
,
582 const unsigned char* expected
,
583 const int expected_len
) {
584 const unsigned char* actual
=
585 reinterpret_cast<const unsigned char*>(actual_frame
.data());
586 CompareCharArraysWithHexError(
587 description
, actual
, actual_frame
.size(), expected
, expected_len
);
590 void CompareFrames(const string
& description
,
591 const SpdyFrame
& expected_frame
,
592 const SpdyFrame
& actual_frame
) {
593 CompareCharArraysWithHexError(
595 reinterpret_cast<const unsigned char*>(expected_frame
.data()),
596 expected_frame
.size(),
597 reinterpret_cast<const unsigned char*>(actual_frame
.data()),
598 actual_frame
.size());
601 // Returns true if the two header blocks have equivalent content.
602 bool CompareHeaderBlocks(const SpdyHeaderBlock
* expected
,
603 const SpdyHeaderBlock
* actual
) {
604 if (expected
->size() != actual
->size()) {
605 LOG(ERROR
) << "Expected " << expected
->size() << " headers; actually got "
606 << actual
->size() << ".";
609 for (SpdyHeaderBlock::const_iterator it
= expected
->begin();
610 it
!= expected
->end();
612 SpdyHeaderBlock::const_iterator it2
= actual
->find(it
->first
);
613 if (it2
== actual
->end()) {
614 LOG(ERROR
) << "Expected header name '" << it
->first
<< "'.";
617 if (it
->second
.compare(it2
->second
) != 0) {
618 LOG(ERROR
) << "Expected header named '" << it
->first
619 << "' to have a value of '" << it
->second
620 << "'. The actual value received was '" << it2
->second
628 bool IsSpdy2() { return spdy_version_
== SPDY2
; }
629 bool IsSpdy3() { return spdy_version_
== SPDY3
; }
630 bool IsSpdy4() { return spdy_version_
== SPDY4
; }
631 bool IsSpdy5() { return spdy_version_
== SPDY5
; }
633 // Version of SPDY protocol to be used.
634 SpdyMajorVersion spdy_version_
;
635 unsigned char spdy_version_ch_
;
638 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
639 INSTANTIATE_TEST_CASE_P(SpdyFramerTests
,
641 ::testing::Values(SPDY2
, SPDY3
, SPDY4
));
643 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
644 TEST_P(SpdyFramerTest
, HeaderBlockInBuffer
) {
645 SpdyFramer
framer(spdy_version_
);
646 framer
.set_enable_compression(false);
648 // Encode the header block into a SynStream frame.
649 SpdySynStreamIR
syn_stream(1);
650 syn_stream
.set_priority(1);
651 syn_stream
.SetHeader("alpha", "beta");
652 syn_stream
.SetHeader("gamma", "charlie");
653 syn_stream
.SetHeader("cookie", "key1=value1; key2=value2");
654 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
655 EXPECT_TRUE(frame
.get() != NULL
);
657 TestSpdyVisitor
visitor(spdy_version_
);
658 visitor
.use_compression_
= false;
659 visitor
.SimulateInFramer(
660 reinterpret_cast<unsigned char*>(frame
->data()),
663 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
664 EXPECT_TRUE(CompareHeaderBlocks(&syn_stream
.name_value_block(),
668 // Test that if there's not a full frame, we fail to parse it.
669 TEST_P(SpdyFramerTest
, UndersizedHeaderBlockInBuffer
) {
670 SpdyFramer
framer(spdy_version_
);
671 framer
.set_enable_compression(false);
673 // Encode the header block into a SynStream frame.
674 SpdySynStreamIR
syn_stream(1);
675 syn_stream
.set_priority(1);
676 syn_stream
.SetHeader("alpha", "beta");
677 syn_stream
.SetHeader("gamma", "charlie");
678 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
679 EXPECT_TRUE(frame
.get() != NULL
);
681 TestSpdyVisitor
visitor(spdy_version_
);
682 visitor
.use_compression_
= false;
683 visitor
.SimulateInFramer(
684 reinterpret_cast<unsigned char*>(frame
->data()),
687 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
688 EXPECT_EQ(0u, visitor
.headers_
.size());
691 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
692 // (but don't crash).
693 TEST_P(SpdyFramerTest
, SynReplyWithStreamIdZero
) {
694 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
695 SpdyFramer
framer(spdy_version_
);
696 framer
.set_visitor(&visitor
);
698 SpdySynReplyIR
syn_reply(0);
699 syn_reply
.SetHeader("alpha", "beta");
700 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeSynReply(syn_reply
));
701 ASSERT_TRUE(frame
.get() != NULL
);
703 // We shouldn't have to read the whole frame before we signal an error.
704 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
705 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
706 EXPECT_TRUE(framer
.HasError());
707 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
708 << SpdyFramer::ErrorCodeToString(framer
.error_code());
711 // Test that if we receive a HEADERS with stream ID zero, we signal an error
712 // (but don't crash).
713 TEST_P(SpdyFramerTest
, HeadersWithStreamIdZero
) {
714 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
715 SpdyFramer
framer(spdy_version_
);
716 framer
.set_visitor(&visitor
);
718 SpdyHeadersIR
headers_ir(0);
719 headers_ir
.SetHeader("alpha", "beta");
720 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeHeaders(headers_ir
));
721 ASSERT_TRUE(frame
.get() != NULL
);
723 // We shouldn't have to read the whole frame before we signal an error.
724 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
725 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
726 EXPECT_TRUE(framer
.HasError());
727 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
728 << SpdyFramer::ErrorCodeToString(framer
.error_code());
731 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
732 // error (but don't crash).
733 TEST_P(SpdyFramerTest
, PushPromiseWithStreamIdZero
) {
734 if (spdy_version_
<= SPDY3
) {
738 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
739 SpdyFramer
framer(spdy_version_
);
740 framer
.set_visitor(&visitor
);
742 SpdyPushPromiseIR
push_promise(0, 4);
743 push_promise
.SetHeader("alpha", "beta");
744 scoped_ptr
<SpdySerializedFrame
> frame(
745 framer
.SerializePushPromise(push_promise
));
746 ASSERT_TRUE(frame
.get() != NULL
);
748 // We shouldn't have to read the whole frame before we signal an error.
749 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
750 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
751 EXPECT_TRUE(framer
.HasError());
752 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
753 << SpdyFramer::ErrorCodeToString(framer
.error_code());
756 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
757 // signal an error (but don't crash).
758 TEST_P(SpdyFramerTest
, PushPromiseWithPromisedStreamIdZero
) {
759 if (spdy_version_
<= SPDY3
) {
763 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
764 SpdyFramer
framer(spdy_version_
);
765 framer
.set_visitor(&visitor
);
767 SpdyPushPromiseIR
push_promise(3, 0);
768 push_promise
.SetHeader("alpha", "beta");
769 scoped_ptr
<SpdySerializedFrame
> frame(
770 framer
.SerializePushPromise(push_promise
));
771 ASSERT_TRUE(frame
.get() != NULL
);
773 // We shouldn't have to read the whole frame before we signal an error.
774 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
775 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
776 EXPECT_TRUE(framer
.HasError());
777 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
778 << SpdyFramer::ErrorCodeToString(framer
.error_code());
781 TEST_P(SpdyFramerTest
, DuplicateHeader
) {
782 if (spdy_version_
> SPDY3
) {
783 // TODO(jgraettinger): Punting on this because we haven't determined
784 // whether duplicate HPACK headers other than Cookie are an error.
785 // If they are, this will need to be updated to use HpackOutputStream.
788 SpdyFramer
framer(spdy_version_
);
789 // Frame builder with plentiful buffer size.
790 SpdyFrameBuilder
frame(1024, spdy_version_
);
791 if (spdy_version_
<= SPDY3
) {
792 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
793 frame
.WriteUInt32(3); // stream_id
794 frame
.WriteUInt32(0); // associated stream id
795 frame
.WriteUInt16(0); // Priority.
797 frame
.BeginNewFrame(framer
, HEADERS
, HEADERS_FLAG_PRIORITY
, 3);
798 frame
.WriteUInt32(framer
.GetHighestPriority());
802 frame
.WriteUInt16(2); // Number of headers.
803 frame
.WriteString("name");
804 frame
.WriteString("value1");
805 frame
.WriteString("name");
806 frame
.WriteString("value2");
808 frame
.WriteUInt32(2); // Number of headers.
809 frame
.WriteStringPiece32("name");
810 frame
.WriteStringPiece32("value1");
811 frame
.WriteStringPiece32("name");
812 frame
.WriteStringPiece32("value2");
815 frame
.RewriteLength(framer
);
817 SpdyHeaderBlock new_headers
;
818 framer
.set_enable_compression(false);
819 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
820 base::StringPiece serialized_headers
=
821 GetSerializedHeaders(control_frame
.get(), framer
);
822 // This should fail because duplicate headers are verboten by the spec.
823 EXPECT_FALSE(framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
824 serialized_headers
.size(),
828 TEST_P(SpdyFramerTest
, MultiValueHeader
) {
829 SpdyFramer
framer(spdy_version_
);
830 // Frame builder with plentiful buffer size.
831 SpdyFrameBuilder
frame(1024, spdy_version_
);
832 if (spdy_version_
<= SPDY3
) {
833 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
834 frame
.WriteUInt32(3); // stream_id
835 frame
.WriteUInt32(0); // associated stream id
836 frame
.WriteUInt16(0); // Priority.
838 frame
.BeginNewFrame(framer
,
840 HEADERS_FLAG_PRIORITY
| HEADERS_FLAG_END_HEADERS
,
842 frame
.WriteUInt32(0); // Priority exclusivity and dependent stream.
843 frame
.WriteUInt8(255); // Priority weight.
846 string
value("value1\0value2", 13);
848 frame
.WriteUInt16(1); // Number of headers.
849 frame
.WriteString("name");
850 frame
.WriteString(value
);
851 } else if (spdy_version_
> SPDY3
) {
852 // TODO(jgraettinger): If this pattern appears again, move to test class.
853 std::map
<string
, string
> header_set
;
854 header_set
["name"] = value
;
856 HpackEncoder
encoder(ObtainHpackHuffmanTable());
857 encoder
.EncodeHeaderSetWithoutCompression(header_set
, &buffer
);
858 frame
.WriteBytes(&buffer
[0], buffer
.size());
860 frame
.WriteUInt32(1); // Number of headers.
861 frame
.WriteStringPiece32("name");
862 frame
.WriteStringPiece32(value
);
865 frame
.RewriteLength(framer
);
867 framer
.set_enable_compression(false);
868 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
870 TestSpdyVisitor
visitor(spdy_version_
);
871 visitor
.use_compression_
= false;
872 visitor
.SimulateInFramer(
873 reinterpret_cast<unsigned char*>(control_frame
->data()),
874 control_frame
->size());
876 EXPECT_THAT(visitor
.headers_
, ElementsAre(
877 Pair("name", value
)));
880 TEST_P(SpdyFramerTest
, BasicCompression
) {
881 if (spdy_version_
> SPDY3
) {
882 // Deflate compression doesn't apply to HPACK.
885 scoped_ptr
<TestSpdyVisitor
> visitor(new TestSpdyVisitor(spdy_version_
));
886 SpdyFramer
framer(spdy_version_
);
887 framer
.set_debug_visitor(visitor
.get());
888 SpdySynStreamIR
syn_stream(1);
889 syn_stream
.set_priority(1);
890 syn_stream
.SetHeader("server", "SpdyServer 1.0");
891 syn_stream
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
892 syn_stream
.SetHeader("status", "200");
893 syn_stream
.SetHeader("version", "HTTP/1.1");
894 syn_stream
.SetHeader("content-type", "text/html");
895 syn_stream
.SetHeader("content-length", "12");
896 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeSynStream(syn_stream
));
897 size_t uncompressed_size1
= visitor
->last_payload_len_
;
898 size_t compressed_size1
=
899 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
901 EXPECT_EQ(139u, uncompressed_size1
);
902 #if defined(USE_SYSTEM_ZLIB)
903 EXPECT_EQ(155u, compressed_size1
);
904 #else // !defined(USE_SYSTEM_ZLIB)
905 EXPECT_EQ(135u, compressed_size1
);
906 #endif // !defined(USE_SYSTEM_ZLIB)
908 EXPECT_EQ(165u, uncompressed_size1
);
909 #if defined(USE_SYSTEM_ZLIB)
910 EXPECT_EQ(181u, compressed_size1
);
911 #else // !defined(USE_SYSTEM_ZLIB)
912 EXPECT_EQ(117u, compressed_size1
);
913 #endif // !defined(USE_SYSTEM_ZLIB)
915 scoped_ptr
<SpdyFrame
> frame2(framer
.SerializeSynStream(syn_stream
));
916 size_t uncompressed_size2
= visitor
->last_payload_len_
;
917 size_t compressed_size2
=
918 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
920 // Expect the second frame to be more compact than the first.
921 EXPECT_LE(frame2
->size(), frame1
->size());
923 // Decompress the first frame
924 scoped_ptr
<SpdyFrame
> frame3(SpdyFramerTestUtil::DecompressFrame(
925 &framer
, *frame1
.get()));
927 // Decompress the second frame
928 visitor
.reset(new TestSpdyVisitor(spdy_version_
));
929 framer
.set_debug_visitor(visitor
.get());
930 scoped_ptr
<SpdyFrame
> frame4(SpdyFramerTestUtil::DecompressFrame(
931 &framer
, *frame2
.get()));
932 size_t uncompressed_size4
=
933 frame4
->size() - framer
.GetSynStreamMinimumSize();
934 size_t compressed_size4
=
935 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
937 EXPECT_EQ(139u, uncompressed_size4
);
938 #if defined(USE_SYSTEM_ZLIB)
939 EXPECT_EQ(149u, compressed_size4
);
940 #else // !defined(USE_SYSTEM_ZLIB)
941 EXPECT_EQ(101u, compressed_size4
);
942 #endif // !defined(USE_SYSTEM_ZLIB)
944 EXPECT_EQ(165u, uncompressed_size4
);
945 #if defined(USE_SYSTEM_ZLIB)
946 EXPECT_EQ(175u, compressed_size4
);
947 #else // !defined(USE_SYSTEM_ZLIB)
948 EXPECT_EQ(102u, compressed_size4
);
949 #endif // !defined(USE_SYSTEM_ZLIB)
952 EXPECT_EQ(uncompressed_size1
, uncompressed_size2
);
953 EXPECT_EQ(uncompressed_size1
, uncompressed_size4
);
954 EXPECT_EQ(compressed_size2
, compressed_size4
);
956 // Expect frames 3 & 4 to be the same.
957 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *frame4
);
959 // Expect frames 3 to be the same as a uncompressed frame created
961 framer
.set_enable_compression(false);
962 scoped_ptr
<SpdyFrame
> uncompressed_frame(
963 framer
.SerializeSynStream(syn_stream
));
964 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *uncompressed_frame
);
967 TEST_P(SpdyFramerTest
, CompressEmptyHeaders
) {
968 // See crbug.com/172383
969 SpdySynStreamIR
syn_stream(1);
970 syn_stream
.SetHeader("server", "SpdyServer 1.0");
971 syn_stream
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
972 syn_stream
.SetHeader("status", "200");
973 syn_stream
.SetHeader("version", "HTTP/1.1");
974 syn_stream
.SetHeader("content-type", "text/html");
975 syn_stream
.SetHeader("content-length", "12");
976 syn_stream
.SetHeader("x-empty-header", "");
978 SpdyFramer
framer(spdy_version_
);
979 framer
.set_enable_compression(true);
980 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeSynStream(syn_stream
));
983 TEST_P(SpdyFramerTest
, Basic
) {
984 const unsigned char kV2Input
[] = {
985 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
986 0x00, 0x00, 0x00, 0x14,
987 0x00, 0x00, 0x00, 0x01,
988 0x00, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x01,
990 0x00, 0x02, 'h', 'h',
991 0x00, 0x02, 'v', 'v',
993 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
994 0x00, 0x00, 0x00, 0x18,
995 0x00, 0x00, 0x00, 0x01,
996 0x00, 0x00, 0x00, 0x02,
997 0x00, 0x02, 'h', '2',
998 0x00, 0x02, 'v', '2',
999 0x00, 0x02, 'h', '3',
1000 0x00, 0x02, 'v', '3',
1002 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1003 0x00, 0x00, 0x00, 0x0c,
1004 0xde, 0xad, 0xbe, 0xef,
1005 0xde, 0xad, 0xbe, 0xef,
1006 0xde, 0xad, 0xbe, 0xef,
1008 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1009 0x00, 0x00, 0x00, 0x0c,
1010 0x00, 0x00, 0x00, 0x03,
1011 0x00, 0x00, 0x00, 0x00,
1012 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1015 0x00, 0x00, 0x00, 0x08,
1016 0xde, 0xad, 0xbe, 0xef,
1017 0xde, 0xad, 0xbe, 0xef,
1019 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1020 0x00, 0x00, 0x00, 0x04,
1021 0xde, 0xad, 0xbe, 0xef,
1023 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1024 0x00, 0x00, 0x00, 0x08,
1025 0x00, 0x00, 0x00, 0x01,
1026 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1028 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1029 0x00, 0x00, 0x00, 0x00,
1031 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1032 0x00, 0x00, 0x00, 0x08,
1033 0x00, 0x00, 0x00, 0x03,
1034 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1037 const unsigned char kV3Input
[] = {
1038 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1039 0x00, 0x00, 0x00, 0x1a,
1040 0x00, 0x00, 0x00, 0x01,
1041 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x00,
1043 0x00, 0x01, 0x00, 0x00,
1044 0x00, 0x02, 'h', 'h',
1045 0x00, 0x00, 0x00, 0x02,
1048 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
1049 0x00, 0x00, 0x00, 0x20,
1050 0x00, 0x00, 0x00, 0x01,
1051 0x00, 0x00, 0x00, 0x02,
1052 0x00, 0x00, 0x00, 0x02,
1054 0x00, 0x00, 0x00, 0x02,
1055 'v', '2', 0x00, 0x00,
1056 0x00, 0x02, 'h', '3',
1057 0x00, 0x00, 0x00, 0x02,
1060 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1061 0x00, 0x00, 0x00, 0x0c,
1062 0xde, 0xad, 0xbe, 0xef,
1063 0xde, 0xad, 0xbe, 0xef,
1064 0xde, 0xad, 0xbe, 0xef,
1066 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1067 0x00, 0x00, 0x00, 0x0e,
1068 0x00, 0x00, 0x00, 0x03,
1069 0x00, 0x00, 0x00, 0x00,
1070 0x00, 0x00, 0x00, 0x00,
1073 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1074 0x00, 0x00, 0x00, 0x08,
1075 0xde, 0xad, 0xbe, 0xef,
1076 0xde, 0xad, 0xbe, 0xef,
1078 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1079 0x00, 0x00, 0x00, 0x04,
1080 0xde, 0xad, 0xbe, 0xef,
1082 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1083 0x00, 0x00, 0x00, 0x08,
1084 0x00, 0x00, 0x00, 0x01,
1085 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1087 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1088 0x00, 0x00, 0x00, 0x00,
1090 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1091 0x00, 0x00, 0x00, 0x08,
1092 0x00, 0x00, 0x00, 0x03,
1093 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1096 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1097 // HEADERS frames with PRIORITY and END_HEADERS set.
1098 const unsigned char kV4Input
[] = {
1099 0x00, 0x05, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS
1100 0x00, 0x00, 0x00, 0x01, // Stream 1
1101 0x00, 0x00, 0x00, 0x00, // Priority 0
1102 0x82, // :method: GET
1104 0x00, 0x01, 0x01, 0x04, // HEADERS: END_HEADERS
1105 0x00, 0x00, 0x00, 0x01, // Stream 1
1106 0x8c, // :status: 200
1108 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1
1109 0x00, 0x00, 0x00, 0x01,
1110 0xde, 0xad, 0xbe, 0xef,
1111 0xde, 0xad, 0xbe, 0xef,
1112 0xde, 0xad, 0xbe, 0xef,
1114 0x00, 0x05, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS
1115 0x00, 0x00, 0x00, 0x03, // Stream 3
1116 0x00, 0x00, 0x00, 0x00, // Priority 0
1117 0x82, // :method: GET
1119 0x00, 0x08, 0x00, 0x00, // DATA on Stream #3
1120 0x00, 0x00, 0x00, 0x03,
1121 0xde, 0xad, 0xbe, 0xef,
1122 0xde, 0xad, 0xbe, 0xef,
1124 0x00, 0x04, 0x00, 0x00, // DATA on Stream #1
1125 0x00, 0x00, 0x00, 0x01,
1126 0xde, 0xad, 0xbe, 0xef,
1128 0x00, 0x04, 0x03, 0x00, // RST_STREAM on Stream #1
1129 0x00, 0x00, 0x00, 0x01,
1130 0x00, 0x00, 0x00, 0x08, // RST_STREAM_CANCEL
1132 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1133 0x00, 0x00, 0x00, 0x03,
1135 0x00, 0x0f, 0x03, 0x00, // RST_STREAM on Stream #3
1136 0x00, 0x00, 0x00, 0x03,
1137 0x00, 0x00, 0x00, 0x08, // RST_STREAM_CANCEL
1138 0x52, 0x45, 0x53, 0x45, // opaque data
1139 0x54, 0x53, 0x54, 0x52,
1143 TestSpdyVisitor
visitor(spdy_version_
);
1145 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1146 } else if (IsSpdy3()) {
1147 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1149 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1152 EXPECT_EQ(2, visitor
.syn_frame_count_
);
1153 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1154 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1155 EXPECT_EQ(24, visitor
.data_bytes_
);
1157 EXPECT_EQ(0, visitor
.error_count_
);
1158 EXPECT_EQ(2, visitor
.fin_frame_count_
);
1161 base::StringPiece reset_stream
= "RESETSTREAM";
1162 EXPECT_EQ(reset_stream
, visitor
.fin_opaque_data_
);
1164 EXPECT_TRUE(visitor
.fin_opaque_data_
.empty());
1167 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1168 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
1169 EXPECT_EQ(4, visitor
.data_frame_count_
);
1170 visitor
.fin_opaque_data_
.clear();
1173 // Test that the FIN flag on a data frame signifies EOF.
1174 TEST_P(SpdyFramerTest
, FinOnDataFrame
) {
1175 const unsigned char kV2Input
[] = {
1176 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1177 0x00, 0x00, 0x00, 0x14,
1178 0x00, 0x00, 0x00, 0x01,
1179 0x00, 0x00, 0x00, 0x00,
1180 0x00, 0x00, 0x00, 0x01,
1181 0x00, 0x02, 'h', 'h',
1182 0x00, 0x02, 'v', 'v',
1184 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1185 0x00, 0x00, 0x00, 0x10,
1186 0x00, 0x00, 0x00, 0x01,
1187 0x00, 0x00, 0x00, 0x01,
1188 0x00, 0x02, 'a', 'a',
1189 0x00, 0x02, 'b', 'b',
1191 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1192 0x00, 0x00, 0x00, 0x0c,
1193 0xde, 0xad, 0xbe, 0xef,
1194 0xde, 0xad, 0xbe, 0xef,
1195 0xde, 0xad, 0xbe, 0xef,
1197 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1198 0x01, 0x00, 0x00, 0x04,
1199 0xde, 0xad, 0xbe, 0xef,
1201 const unsigned char kV3Input
[] = {
1202 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1203 0x00, 0x00, 0x00, 0x1a,
1204 0x00, 0x00, 0x00, 0x01,
1205 0x00, 0x00, 0x00, 0x00,
1206 0x00, 0x00, 0x00, 0x00,
1207 0x00, 0x01, 0x00, 0x00,
1208 0x00, 0x02, 'h', 'h',
1209 0x00, 0x00, 0x00, 0x02,
1212 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1213 0x00, 0x00, 0x00, 0x14,
1214 0x00, 0x00, 0x00, 0x01,
1215 0x00, 0x00, 0x00, 0x01,
1216 0x00, 0x00, 0x00, 0x02,
1217 'a', 'a', 0x00, 0x00,
1218 0x00, 0x02, 'b', 'b',
1220 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1221 0x00, 0x00, 0x00, 0x0c,
1222 0xde, 0xad, 0xbe, 0xef,
1223 0xde, 0xad, 0xbe, 0xef,
1224 0xde, 0xad, 0xbe, 0xef,
1226 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1227 0x01, 0x00, 0x00, 0x04,
1228 0xde, 0xad, 0xbe, 0xef,
1231 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1232 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1233 const unsigned char kV4Input
[] = {
1234 0x00, 0x05, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS
1235 0x00, 0x00, 0x00, 0x01, // Stream 1
1236 0x00, 0x00, 0x00, 0x00, // Priority 0
1237 0x82, // :method: GET
1239 0x00, 0x01, 0x01, 0x04, // HEADERS: END_HEADERS
1240 0x00, 0x00, 0x00, 0x01, // Stream 1
1241 0x8c, // :status: 200
1243 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1
1244 0x00, 0x00, 0x00, 0x01,
1245 0xde, 0xad, 0xbe, 0xef,
1246 0xde, 0xad, 0xbe, 0xef,
1247 0xde, 0xad, 0xbe, 0xef,
1249 0x00, 0x04, 0x00, 0x01, // DATA on Stream #1, with FIN
1250 0x00, 0x00, 0x00, 0x01,
1251 0xde, 0xad, 0xbe, 0xef,
1254 TestSpdyVisitor
visitor(spdy_version_
);
1256 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1257 } else if (IsSpdy3()) {
1258 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1260 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1263 EXPECT_EQ(0, visitor
.error_count_
);
1264 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1266 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1267 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1269 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1270 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1272 EXPECT_EQ(16, visitor
.data_bytes_
);
1273 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1274 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1275 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1276 EXPECT_EQ(2, visitor
.data_frame_count_
);
1279 // Test that the FIN flag on a SYN reply frame signifies EOF.
1280 TEST_P(SpdyFramerTest
, FinOnSynReplyFrame
) {
1281 const unsigned char kV2Input
[] = {
1282 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1283 0x00, 0x00, 0x00, 0x14,
1284 0x00, 0x00, 0x00, 0x01,
1285 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x01,
1287 0x00, 0x02, 'h', 'h',
1288 0x00, 0x02, 'v', 'v',
1290 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1291 0x01, 0x00, 0x00, 0x10,
1292 0x00, 0x00, 0x00, 0x01,
1293 0x00, 0x00, 0x00, 0x01,
1294 0x00, 0x02, 'a', 'a',
1295 0x00, 0x02, 'b', 'b',
1297 const unsigned char kV3Input
[] = {
1298 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1299 0x00, 0x00, 0x00, 0x1a,
1300 0x00, 0x00, 0x00, 0x01,
1301 0x00, 0x00, 0x00, 0x00,
1302 0x00, 0x00, 0x00, 0x00,
1303 0x00, 0x01, 0x00, 0x00,
1304 0x00, 0x02, 'h', 'h',
1305 0x00, 0x00, 0x00, 0x02,
1308 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1309 0x01, 0x00, 0x00, 0x14,
1310 0x00, 0x00, 0x00, 0x01,
1311 0x00, 0x00, 0x00, 0x01,
1312 0x00, 0x00, 0x00, 0x02,
1313 'a', 'a', 0x00, 0x00,
1314 0x00, 0x02, 'b', 'b',
1317 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1318 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1319 const unsigned char kV4Input
[] = {
1320 0x00, 0x05, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS
1321 0x00, 0x00, 0x00, 0x01, // Stream 1
1322 0x00, 0x00, 0x00, 0x00, // Priority 0
1323 0x82, // :method: GET
1325 0x00, 0x01, 0x01, 0x05, // HEADERS: FIN | END_HEADERS
1326 0x00, 0x00, 0x00, 0x01, // Stream 1
1327 0x8c, // :status: 200
1330 TestSpdyVisitor
visitor(spdy_version_
);
1332 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1333 } else if (IsSpdy3()) {
1334 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1336 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1339 EXPECT_EQ(0, visitor
.error_count_
);
1340 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1342 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1343 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1345 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1346 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1348 EXPECT_EQ(0, visitor
.data_bytes_
);
1349 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1350 EXPECT_EQ(1, visitor
.fin_flag_count_
);
1351 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1352 EXPECT_EQ(0, visitor
.data_frame_count_
);
1355 TEST_P(SpdyFramerTest
, HeaderCompression
) {
1356 if (spdy_version_
> SPDY3
) {
1357 // Deflate compression doesn't apply to HPACK.
1360 SpdyFramer
send_framer(spdy_version_
);
1361 SpdyFramer
recv_framer(spdy_version_
);
1363 send_framer
.set_enable_compression(true);
1364 recv_framer
.set_enable_compression(true);
1366 const char kHeader1
[] = "header1";
1367 const char kHeader2
[] = "header2";
1368 const char kHeader3
[] = "header3";
1369 const char kValue1
[] = "value1";
1370 const char kValue2
[] = "value2";
1371 const char kValue3
[] = "value3";
1374 SpdyHeaderBlock block
;
1375 block
[kHeader1
] = kValue1
;
1376 block
[kHeader2
] = kValue2
;
1377 SpdySynStreamIR
syn_ir_1(1);
1378 syn_ir_1
.set_name_value_block(block
);
1379 scoped_ptr
<SpdyFrame
> syn_frame_1(send_framer
.SerializeFrame(syn_ir_1
));
1380 EXPECT_TRUE(syn_frame_1
.get() != NULL
);
1383 block
[kHeader3
] = kValue3
;
1384 SpdySynStreamIR
syn_stream(3);
1385 syn_stream
.set_name_value_block(block
);
1386 scoped_ptr
<SpdyFrame
> syn_frame_2(send_framer
.SerializeSynStream(syn_stream
));
1387 EXPECT_TRUE(syn_frame_2
.get() != NULL
);
1389 // Now start decompressing
1390 scoped_ptr
<SpdyFrame
> decompressed
;
1391 scoped_ptr
<SpdyFrame
> uncompressed
;
1392 base::StringPiece serialized_headers
;
1393 SpdyHeaderBlock decompressed_headers
;
1395 // Decompress SYN_STREAM #1
1396 decompressed
.reset(SpdyFramerTestUtil::DecompressFrame(
1397 &recv_framer
, *syn_frame_1
.get()));
1398 EXPECT_TRUE(decompressed
.get() != NULL
);
1399 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1400 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1401 serialized_headers
.size(),
1402 &decompressed_headers
));
1403 EXPECT_EQ(2u, decompressed_headers
.size());
1404 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1405 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1407 // Decompress SYN_STREAM #2
1408 decompressed
.reset(SpdyFramerTestUtil::DecompressFrame(
1409 &recv_framer
, *syn_frame_2
.get()));
1410 EXPECT_TRUE(decompressed
.get() != NULL
);
1411 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1412 decompressed_headers
.clear();
1413 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1414 serialized_headers
.size(),
1415 &decompressed_headers
));
1416 EXPECT_EQ(3u, decompressed_headers
.size());
1417 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1418 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1419 EXPECT_EQ(kValue3
, decompressed_headers
[kHeader3
]);
1422 // Verify we don't leak when we leave streams unclosed
1423 TEST_P(SpdyFramerTest
, UnclosedStreamDataCompressors
) {
1424 SpdyFramer
send_framer(spdy_version_
);
1426 send_framer
.set_enable_compression(true);
1428 const char kHeader1
[] = "header1";
1429 const char kHeader2
[] = "header2";
1430 const char kValue1
[] = "value1";
1431 const char kValue2
[] = "value2";
1433 SpdySynStreamIR
syn_stream(1);
1434 syn_stream
.SetHeader(kHeader1
, kValue1
);
1435 syn_stream
.SetHeader(kHeader2
, kValue2
);
1436 scoped_ptr
<SpdyFrame
> syn_frame(send_framer
.SerializeSynStream(syn_stream
));
1437 EXPECT_TRUE(syn_frame
.get() != NULL
);
1439 StringPiece bytes
= "this is a test test test test test!";
1440 SpdyDataIR
data_ir(1, bytes
);
1441 data_ir
.set_fin(true);
1442 scoped_ptr
<SpdyFrame
> send_frame(send_framer
.SerializeData(data_ir
));
1443 EXPECT_TRUE(send_frame
.get() != NULL
);
1445 // Run the inputs through the framer.
1446 TestSpdyVisitor
visitor(spdy_version_
);
1447 visitor
.use_compression_
= true;
1448 const unsigned char* data
;
1449 data
= reinterpret_cast<const unsigned char*>(syn_frame
->data());
1450 visitor
.SimulateInFramer(data
, syn_frame
->size());
1451 data
= reinterpret_cast<const unsigned char*>(send_frame
->data());
1452 visitor
.SimulateInFramer(data
, send_frame
->size());
1454 EXPECT_EQ(0, visitor
.error_count_
);
1455 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1456 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1457 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1458 EXPECT_EQ(bytes
.size(), static_cast<unsigned>(visitor
.data_bytes_
));
1459 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1460 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1461 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1462 EXPECT_EQ(1, visitor
.data_frame_count_
);
1465 // Verify we can decompress the stream even if handed over to the
1466 // framer 1 byte at a time.
1467 TEST_P(SpdyFramerTest
, UnclosedStreamDataCompressorsOneByteAtATime
) {
1468 SpdyFramer
send_framer(spdy_version_
);
1470 send_framer
.set_enable_compression(true);
1472 const char kHeader1
[] = "header1";
1473 const char kHeader2
[] = "header2";
1474 const char kValue1
[] = "value1";
1475 const char kValue2
[] = "value2";
1477 SpdySynStreamIR
syn_stream(1);
1478 syn_stream
.SetHeader(kHeader1
, kValue1
);
1479 syn_stream
.SetHeader(kHeader2
, kValue2
);
1480 scoped_ptr
<SpdyFrame
> syn_frame(send_framer
.SerializeSynStream(syn_stream
));
1481 EXPECT_TRUE(syn_frame
.get() != NULL
);
1483 const char bytes
[] = "this is a test test test test test!";
1484 SpdyDataIR
data_ir(1, StringPiece(bytes
, arraysize(bytes
)));
1485 data_ir
.set_fin(true);
1486 scoped_ptr
<SpdyFrame
> send_frame(send_framer
.SerializeData(data_ir
));
1487 EXPECT_TRUE(send_frame
.get() != NULL
);
1489 // Run the inputs through the framer.
1490 TestSpdyVisitor
visitor(spdy_version_
);
1491 visitor
.use_compression_
= true;
1492 const unsigned char* data
;
1493 data
= reinterpret_cast<const unsigned char*>(syn_frame
->data());
1494 for (size_t idx
= 0; idx
< syn_frame
->size(); ++idx
) {
1495 visitor
.SimulateInFramer(data
+ idx
, 1);
1496 ASSERT_EQ(0, visitor
.error_count_
);
1498 data
= reinterpret_cast<const unsigned char*>(send_frame
->data());
1499 for (size_t idx
= 0; idx
< send_frame
->size(); ++idx
) {
1500 visitor
.SimulateInFramer(data
+ idx
, 1);
1501 ASSERT_EQ(0, visitor
.error_count_
);
1504 EXPECT_EQ(0, visitor
.error_count_
);
1505 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1506 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1507 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1508 EXPECT_EQ(arraysize(bytes
), static_cast<unsigned>(visitor
.data_bytes_
));
1509 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1510 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1511 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1512 EXPECT_EQ(1, visitor
.data_frame_count_
);
1515 TEST_P(SpdyFramerTest
, WindowUpdateFrame
) {
1516 SpdyFramer
framer(spdy_version_
);
1517 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
1518 SpdyWindowUpdateIR(1, 0x12345678)));
1520 const char kDescription
[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1521 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1522 0x80, spdy_version_ch_
, 0x00, 0x09,
1523 0x00, 0x00, 0x00, 0x08,
1524 0x00, 0x00, 0x00, 0x01,
1525 0x12, 0x34, 0x56, 0x78
1527 const unsigned char kV4FrameData
[] = {
1528 0x00, 0x04, 0x08, 0x00,
1529 0x00, 0x00, 0x00, 0x01,
1530 0x12, 0x34, 0x56, 0x78
1534 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1536 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1540 TEST_P(SpdyFramerTest
, CreateDataFrame
) {
1541 SpdyFramer
framer(spdy_version_
);
1544 const char kDescription
[] = "'hello' data frame, no FIN";
1545 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1546 0x00, 0x00, 0x00, 0x01,
1547 0x00, 0x00, 0x00, 0x05,
1551 const unsigned char kV4FrameData
[] = {
1552 0x00, 0x05, 0x00, 0x00,
1553 0x00, 0x00, 0x00, 0x01,
1557 const char bytes
[] = "hello";
1559 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1560 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1563 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1566 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1569 SpdyDataIR
data_header_ir(1);
1570 data_header_ir
.SetDataShallow(base::StringPiece(bytes
, strlen(bytes
)));
1571 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(
1573 CompareCharArraysWithHexError(
1575 reinterpret_cast<const unsigned char*>(frame
->data()),
1576 framer
.GetDataFrameMinimumSize(),
1577 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1578 framer
.GetDataFrameMinimumSize());
1582 const char kDescription
[] = "'hello' data frame with more padding, no FIN";
1583 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1584 0x00, 0x00, 0x00, 0x01,
1585 0x00, 0x00, 0x00, 0x05,
1590 const unsigned char kV4FrameData
[] = {
1591 0x01, 0x0b, 0x00, 0x18, // Length = 267. PAD_HIGH and PAD_LOW set.
1592 0x00, 0x00, 0x00, 0x01,
1593 0x01, 0x04, // Pad Low and Pad High fields.
1594 'h', 'e', 'l', 'l', // Data
1596 // Padding of 260 zeros (so both PAD_HIGH and PAD_LOW fields are used).
1597 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1598 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1599 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1600 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1601 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1602 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1603 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1604 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1605 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1606 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1607 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1608 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1609 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1610 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1611 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1612 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1613 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1614 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1615 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1616 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1618 const char bytes
[] = "hello";
1620 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1621 // 260 zeros and the pad low/high fields make the overall padding to be 262
1623 data_ir
.set_padding_len(262);
1624 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1627 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1630 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1633 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1634 CompareCharArraysWithHexError(
1636 reinterpret_cast<const unsigned char*>(frame
->data()),
1637 framer
.GetDataFrameMinimumSize(),
1638 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1639 framer
.GetDataFrameMinimumSize());
1643 const char kDescription
[] = "'hello' data frame with few padding, no FIN";
1644 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1645 0x00, 0x00, 0x00, 0x01,
1646 0x00, 0x00, 0x00, 0x05,
1651 const unsigned char kV4FrameData
[] = {
1652 0x00, 0x0d, 0x00, 0x08, // Length = 13. PAD_LOW set.
1653 0x00, 0x00, 0x00, 0x01,
1654 0x07, // Pad Low field.
1655 'h', 'e', 'l', 'l', // Data
1657 '0', '0', '0', '0', // Padding
1660 const char bytes
[] = "hello";
1662 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1663 // 7 zeros and the pad low field make the overall padding to be 8 bytes.
1664 data_ir
.set_padding_len(8);
1665 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1668 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1671 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1676 const char kDescription
[] =
1677 "'hello' data frame with 1 byte padding, no FIN";
1678 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1679 0x00, 0x00, 0x00, 0x01,
1680 0x00, 0x00, 0x00, 0x05,
1685 const unsigned char kV4FrameData
[] = {
1686 0x00, 0x06, 0x00, 0x08, // Length = 6. PAD_LOW set.
1687 0x00, 0x00, 0x00, 0x01,
1688 0x00, // Pad Low field.
1689 'h', 'e', 'l', 'l', // Data
1692 const char bytes
[] = "hello";
1694 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1695 // The pad low field itself is used for the 1-byte padding and no padding
1696 // payload is needed.
1697 data_ir
.set_padding_len(1);
1698 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1701 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1704 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1707 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1708 CompareCharArraysWithHexError(
1710 reinterpret_cast<const unsigned char*>(frame
->data()),
1711 framer
.GetDataFrameMinimumSize(),
1712 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1713 framer
.GetDataFrameMinimumSize());
1717 const char kDescription
[] = "Data frame with negative data byte, no FIN";
1718 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1719 0x00, 0x00, 0x00, 0x01,
1720 0x00, 0x00, 0x00, 0x01,
1723 const unsigned char kV4FrameData
[] = {
1724 0x00, 0x01, 0x00, 0x00,
1725 0x00, 0x00, 0x00, 0x01,
1728 SpdyDataIR
data_ir(1, StringPiece("\xff", 1));
1729 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1732 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1735 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1740 const char kDescription
[] = "'hello' data frame, with FIN";
1741 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1742 0x00, 0x00, 0x00, 0x01,
1743 0x01, 0x00, 0x00, 0x05,
1747 const unsigned char kV4FrameData
[] = {
1748 0x00, 0x05, 0x00, 0x01,
1749 0x00, 0x00, 0x00, 0x01,
1753 SpdyDataIR
data_ir(1, StringPiece("hello", 5));
1754 data_ir
.set_fin(true);
1755 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1758 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1761 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1766 const char kDescription
[] = "Empty data frame";
1767 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1768 0x00, 0x00, 0x00, 0x01,
1769 0x00, 0x00, 0x00, 0x00,
1771 const unsigned char kV4FrameData
[] = {
1772 0x00, 0x00, 0x00, 0x00,
1773 0x00, 0x00, 0x00, 0x01,
1775 SpdyDataIR
data_ir(1, StringPiece());
1776 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1779 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1782 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1785 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1786 CompareCharArraysWithHexError(
1788 reinterpret_cast<const unsigned char*>(frame
->data()),
1789 framer
.GetDataFrameMinimumSize(),
1790 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1791 framer
.GetDataFrameMinimumSize());
1795 const char kDescription
[] = "Data frame with max stream ID";
1796 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1797 0x7f, 0xff, 0xff, 0xff,
1798 0x01, 0x00, 0x00, 0x05,
1802 const unsigned char kV4FrameData
[] = {
1803 0x00, 0x05, 0x00, 0x01,
1804 0x7f, 0xff, 0xff, 0xff,
1808 SpdyDataIR
data_ir(0x7fffffff, "hello");
1809 data_ir
.set_fin(true);
1810 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1813 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1816 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1821 // This test does not apply to SPDY 4 because the max frame size is smaller
1823 const char kDescription
[] = "Large data frame";
1824 const int kDataSize
= 4 * 1024 * 1024; // 4 MB
1825 const string
kData(kDataSize
, 'A');
1826 const unsigned char kFrameHeader
[] = {
1827 0x00, 0x00, 0x00, 0x01,
1828 0x01, 0x40, 0x00, 0x00,
1831 const int kFrameSize
= arraysize(kFrameHeader
) + kDataSize
;
1832 scoped_ptr
<unsigned char[]> expected_frame_data(
1833 new unsigned char[kFrameSize
]);
1834 memcpy(expected_frame_data
.get(), kFrameHeader
, arraysize(kFrameHeader
));
1835 memset(expected_frame_data
.get() + arraysize(kFrameHeader
), 'A', kDataSize
);
1837 SpdyDataIR
data_ir(1, StringPiece(kData
.data(), kData
.size()));
1838 data_ir
.set_fin(true);
1839 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1840 CompareFrame(kDescription
, *frame
, expected_frame_data
.get(), kFrameSize
);
1844 TEST_P(SpdyFramerTest
, CreateSynStreamUncompressed
) {
1845 SpdyFramer
framer(spdy_version_
);
1846 framer
.set_enable_compression(false);
1849 const char kDescription
[] = "SYN_STREAM frame, lowest pri, no FIN";
1851 const unsigned char kPri
= IsSpdy2() ? 0xC0 : 0xE0;
1852 const unsigned char kV2FrameData
[] = {
1853 0x80, spdy_version_ch_
, 0x00, 0x01,
1854 0x00, 0x00, 0x00, 0x20,
1855 0x00, 0x00, 0x00, 0x01,
1856 0x00, 0x00, 0x00, 0x00,
1857 kPri
, 0x00, 0x00, 0x02,
1858 0x00, 0x03, 'b', 'a',
1859 'r', 0x00, 0x03, 'f',
1860 'o', 'o', 0x00, 0x03,
1861 'f', 'o', 'o', 0x00,
1864 const unsigned char kV3FrameData
[] = {
1865 0x80, spdy_version_ch_
, 0x00, 0x01,
1866 0x00, 0x00, 0x00, 0x2a,
1867 0x00, 0x00, 0x00, 0x01,
1868 0x00, 0x00, 0x00, 0x00,
1869 kPri
, 0x00, 0x00, 0x00,
1870 0x00, 0x02, 0x00, 0x00,
1871 0x00, 0x03, 'b', 'a',
1872 'r', 0x00, 0x00, 0x00,
1873 0x03, 'f', 'o', 'o',
1874 0x00, 0x00, 0x00, 0x03,
1875 'f', 'o', 'o', 0x00,
1876 0x00, 0x00, 0x03, 'b',
1879 const unsigned char kV4FrameData
[] = {
1880 0x00, 0x17, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS
1881 0x00, 0x00, 0x00, 0x01, // Stream 1
1882 0x00, 0x00, 0x00, 0x00, // Non-exclusive dependency 0. Weight 0.
1883 0x00, 0x00, 0x03, 0x62,
1884 0x61, 0x72, 0x03, 0x66,
1885 0x6f, 0x6f, 0x00, 0x03,
1886 0x66, 0x6f, 0x6f, 0x03,
1889 SpdySynStreamIR
syn_stream(1);
1890 syn_stream
.set_priority(framer
.GetLowestPriority());
1891 syn_stream
.SetHeader("bar", "foo");
1892 syn_stream
.SetHeader("foo", "bar");
1893 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1895 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1896 } else if (IsSpdy3()) {
1897 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1899 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1904 const char kDescription
[] =
1905 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1908 const unsigned char kV2FrameData
[] = {
1909 0x80, spdy_version_ch_
, 0x00, 0x01,
1910 0x01, 0x00, 0x00, 0x1D,
1911 0x7f, 0xff, 0xff, 0xff,
1912 0x7f, 0xff, 0xff, 0xff,
1913 0x00, 0x00, 0x00, 0x02,
1914 0x00, 0x00, 0x00, 0x03,
1915 'f', 'o', 'o', 0x00,
1916 0x03, 'f', 'o', 'o',
1917 0x00, 0x03, 'b', 'a',
1920 const unsigned char kV3FrameData
[] = {
1921 0x80, spdy_version_ch_
, 0x00, 0x01,
1922 0x01, 0x00, 0x00, 0x27,
1923 0x7f, 0xff, 0xff, 0xff,
1924 0x7f, 0xff, 0xff, 0xff,
1925 0x00, 0x00, 0x00, 0x00,
1926 0x00, 0x02, 0x00, 0x00,
1927 0x00, 0x00, 0x00, 0x00,
1928 0x00, 0x03, 'f', 'o',
1929 'o', 0x00, 0x00, 0x00,
1930 0x03, 'f', 'o', 'o',
1931 0x00, 0x00, 0x00, 0x03,
1934 const unsigned char kV4FrameData
[] = {
1935 0x00, 0x14, 0x01, 0x25, // HEADERS: PRIORITY | FIN | END_HEADERS
1936 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1937 0x00, 0x00, 0x00, 0x00, // Non-exclusive dependency 0. Weight 255.
1938 0xff, 0x00, 0x00, 0x03,
1939 0x66, 0x6f, 0x6f, 0x00,
1940 0x03, 0x66, 0x6f, 0x6f,
1941 0x03, 0x62, 0x61, 0x72,
1943 SpdySynStreamIR
syn_stream(0x7fffffff);
1944 syn_stream
.set_associated_to_stream_id(0x7fffffff);
1945 syn_stream
.set_priority(framer
.GetHighestPriority());
1946 syn_stream
.set_fin(true);
1947 syn_stream
.SetHeader("", "foo");
1948 syn_stream
.SetHeader("foo", "bar");
1949 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1951 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1952 } else if (IsSpdy3()) {
1953 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1955 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1960 const char kDescription
[] =
1961 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1964 const unsigned char kPri
= IsSpdy2() ? 0x40 : 0x20;
1965 const unsigned char kV2FrameData
[] = {
1966 0x80, spdy_version_ch_
, 0x00, 0x01,
1967 0x01, 0x00, 0x00, 0x1D,
1968 0x7f, 0xff, 0xff, 0xff,
1969 0x7f, 0xff, 0xff, 0xff,
1970 kPri
, 0x00, 0x00, 0x02,
1971 0x00, 0x03, 'b', 'a',
1972 'r', 0x00, 0x03, 'f',
1973 'o', 'o', 0x00, 0x03,
1974 'f', 'o', 'o', 0x00,
1977 const unsigned char kV3FrameData
[] = {
1978 0x80, spdy_version_ch_
, 0x00, 0x01,
1979 0x01, 0x00, 0x00, 0x27,
1980 0x7f, 0xff, 0xff, 0xff,
1981 0x7f, 0xff, 0xff, 0xff,
1982 kPri
, 0x00, 0x00, 0x00,
1983 0x00, 0x02, 0x00, 0x00,
1984 0x00, 0x03, 'b', 'a',
1985 'r', 0x00, 0x00, 0x00,
1986 0x03, 'f', 'o', 'o',
1987 0x00, 0x00, 0x00, 0x03,
1988 'f', 'o', 'o', 0x00,
1991 const unsigned char kV4FrameData
[] = {
1992 0x00, 0x14, 0x01, 0x25, // HEADERS: PRIORITY | FIN | END_HEADERS
1993 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1994 0x00, 0x00, 0x00, 0x00, // Non-exclusive dependency 0. Weight 219.
1995 0xdb, 0x00, 0x03, 0x62,
1996 0x61, 0x72, 0x03, 0x66,
1997 0x6f, 0x6f, 0x00, 0x03,
1998 0x66, 0x6f, 0x6f, 0x00,
2000 SpdySynStreamIR
syn_stream(0x7fffffff);
2001 syn_stream
.set_associated_to_stream_id(0x7fffffff);
2002 syn_stream
.set_priority(1);
2003 syn_stream
.set_fin(true);
2004 syn_stream
.SetHeader("bar", "foo");
2005 syn_stream
.SetHeader("foo", "");
2006 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
2008 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2009 } else if (IsSpdy3()) {
2010 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2012 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2017 // TODO(phajdan.jr): Clean up after we no longer need
2018 // to workaround http://crbug.com/139744.
2019 #if !defined(USE_SYSTEM_ZLIB)
2020 TEST_P(SpdyFramerTest
, CreateSynStreamCompressed
) {
2021 SpdyFramer
framer(spdy_version_
);
2022 framer
.set_enable_compression(true);
2025 const char kDescription
[] =
2026 "SYN_STREAM frame, low pri, no FIN";
2028 const SpdyPriority priority
= IsSpdy2() ? 2 : 4;
2029 const unsigned char kV2FrameData
[] = {
2030 0x80, spdy_version_ch_
, 0x00, 0x01,
2031 0x00, 0x00, 0x00, 0x36,
2032 0x00, 0x00, 0x00, 0x01,
2033 0x00, 0x00, 0x00, 0x00,
2034 0x80, 0x00, 0x38, 0xea,
2035 0xdf, 0xa2, 0x51, 0xb2,
2036 0x62, 0x60, 0x62, 0x60,
2037 0x4e, 0x4a, 0x2c, 0x62,
2038 0x60, 0x06, 0x08, 0xa0,
2039 0xb4, 0xfc, 0x7c, 0x80,
2040 0x00, 0x62, 0x60, 0x4e,
2041 0xcb, 0xcf, 0x67, 0x60,
2042 0x06, 0x08, 0xa0, 0xa4,
2043 0xc4, 0x22, 0x80, 0x00,
2044 0x02, 0x00, 0x00, 0x00,
2047 const unsigned char kV3FrameData
[] = {
2048 0x80, spdy_version_ch_
, 0x00, 0x01,
2049 0x00, 0x00, 0x00, 0x37,
2050 0x00, 0x00, 0x00, 0x01,
2051 0x00, 0x00, 0x00, 0x00,
2052 0x80, 0x00, 0x38, 0xEA,
2053 0xE3, 0xC6, 0xA7, 0xC2,
2054 0x02, 0xE5, 0x0E, 0x50,
2055 0xC2, 0x4B, 0x4A, 0x04,
2056 0xE5, 0x0B, 0x66, 0x80,
2057 0x00, 0x4A, 0xCB, 0xCF,
2058 0x07, 0x08, 0x20, 0x10,
2059 0x95, 0x96, 0x9F, 0x0F,
2060 0xA2, 0x00, 0x02, 0x28,
2061 0x29, 0xB1, 0x08, 0x20,
2062 0x80, 0x00, 0x00, 0x00,
2065 SpdySynStreamIR
syn_stream(1);
2066 syn_stream
.set_priority(priority
);
2067 syn_stream
.SetHeader("bar", "foo");
2068 syn_stream
.SetHeader("foo", "bar");
2069 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
2071 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2072 } else if (IsSpdy3()) {
2073 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2075 // Deflate compression doesn't apply to HPACK.
2079 #endif // !defined(USE_SYSTEM_ZLIB)
2081 TEST_P(SpdyFramerTest
, CreateSynReplyUncompressed
) {
2082 SpdyFramer
framer(spdy_version_
);
2083 framer
.set_enable_compression(false);
2086 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2088 const unsigned char kV2FrameData
[] = {
2089 0x80, spdy_version_ch_
, 0x00, 0x02,
2090 0x00, 0x00, 0x00, 0x1C,
2091 0x00, 0x00, 0x00, 0x01,
2092 0x00, 0x00, 0x00, 0x02,
2093 0x00, 0x03, 'b', 'a',
2094 'r', 0x00, 0x03, 'f',
2095 'o', 'o', 0x00, 0x03,
2096 'f', 'o', 'o', 0x00,
2099 const unsigned char kV3FrameData
[] = {
2100 0x80, spdy_version_ch_
, 0x00, 0x02,
2101 0x00, 0x00, 0x00, 0x24,
2102 0x00, 0x00, 0x00, 0x01,
2103 0x00, 0x00, 0x00, 0x02,
2104 0x00, 0x00, 0x00, 0x03,
2105 'b', 'a', 'r', 0x00,
2106 0x00, 0x00, 0x03, 'f',
2107 'o', 'o', 0x00, 0x00,
2108 0x00, 0x03, 'f', 'o',
2109 'o', 0x00, 0x00, 0x00,
2112 const unsigned char kV4FrameData
[] = {
2113 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
2114 0x00, 0x00, 0x00, 0x01, // Stream 1
2115 0x00, 0x03, 0x62, 0x61, // @.ba
2116 0x72, 0x03, 0x66, 0x6f, // r.fo
2117 0x6f, 0x00, 0x03, 0x66, // o@.f
2118 0x6f, 0x6f, 0x03, 0x62, // oo.b
2121 SpdySynReplyIR
syn_reply(1);
2122 syn_reply
.SetHeader("bar", "foo");
2123 syn_reply
.SetHeader("foo", "bar");
2124 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2126 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2127 } else if (IsSpdy3()) {
2128 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2130 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2135 const char kDescription
[] =
2136 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2138 const unsigned char kV2FrameData
[] = {
2139 0x80, spdy_version_ch_
, 0x00, 0x02,
2140 0x01, 0x00, 0x00, 0x19,
2141 0x7f, 0xff, 0xff, 0xff,
2142 0x00, 0x00, 0x00, 0x02,
2143 0x00, 0x00, 0x00, 0x03,
2144 'f', 'o', 'o', 0x00,
2145 0x03, 'f', 'o', 'o',
2146 0x00, 0x03, 'b', 'a',
2149 const unsigned char kV3FrameData
[] = {
2150 0x80, spdy_version_ch_
, 0x00, 0x02,
2151 0x01, 0x00, 0x00, 0x21,
2152 0x7f, 0xff, 0xff, 0xff,
2153 0x00, 0x00, 0x00, 0x02,
2154 0x00, 0x00, 0x00, 0x00,
2155 0x00, 0x00, 0x00, 0x03,
2156 'f', 'o', 'o', 0x00,
2157 0x00, 0x00, 0x03, 'f',
2158 'o', 'o', 0x00, 0x00,
2159 0x00, 0x03, 'b', 'a',
2162 const unsigned char kV4FrameData
[] = {
2163 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2164 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2165 0x00, 0x00, 0x03, 0x66, // @..f
2166 0x6f, 0x6f, 0x00, 0x03, // oo@.
2167 0x66, 0x6f, 0x6f, 0x03, // foo.
2168 0x62, 0x61, 0x72, // bar
2170 SpdySynReplyIR
syn_reply(0x7fffffff);
2171 syn_reply
.set_fin(true);
2172 syn_reply
.SetHeader("", "foo");
2173 syn_reply
.SetHeader("foo", "bar");
2174 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2176 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2177 } else if (IsSpdy3()) {
2178 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2180 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2185 const char kDescription
[] =
2186 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2188 const unsigned char kV2FrameData
[] = {
2189 0x80, spdy_version_ch_
, 0x00, 0x02,
2190 0x01, 0x00, 0x00, 0x19,
2191 0x7f, 0xff, 0xff, 0xff,
2192 0x00, 0x00, 0x00, 0x02,
2193 0x00, 0x03, 'b', 'a',
2194 'r', 0x00, 0x03, 'f',
2195 'o', 'o', 0x00, 0x03,
2196 'f', 'o', 'o', 0x00,
2199 const unsigned char kV3FrameData
[] = {
2200 0x80, spdy_version_ch_
, 0x00, 0x02,
2201 0x01, 0x00, 0x00, 0x21,
2202 0x7f, 0xff, 0xff, 0xff,
2203 0x00, 0x00, 0x00, 0x02,
2204 0x00, 0x00, 0x00, 0x03,
2205 'b', 'a', 'r', 0x00,
2206 0x00, 0x00, 0x03, 'f',
2207 'o', 'o', 0x00, 0x00,
2208 0x00, 0x03, 'f', 'o',
2209 'o', 0x00, 0x00, 0x00,
2212 const unsigned char kV4FrameData
[] = {
2213 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2214 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2215 0x00, 0x03, 0x62, 0x61, // @.ba
2216 0x72, 0x03, 0x66, 0x6f, // r.fo
2217 0x6f, 0x00, 0x03, 0x66, // o@.f
2218 0x6f, 0x6f, 0x00, // oo.
2220 SpdySynReplyIR
syn_reply(0x7fffffff);
2221 syn_reply
.set_fin(true);
2222 syn_reply
.SetHeader("bar", "foo");
2223 syn_reply
.SetHeader("foo", "");
2224 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2226 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2227 } else if (IsSpdy3()) {
2228 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2230 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2235 // TODO(phajdan.jr): Clean up after we no longer need
2236 // to workaround http://crbug.com/139744.
2237 #if !defined(USE_SYSTEM_ZLIB)
2238 TEST_P(SpdyFramerTest
, CreateSynReplyCompressed
) {
2239 SpdyFramer
framer(spdy_version_
);
2240 framer
.set_enable_compression(true);
2243 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2245 const unsigned char kV2FrameData
[] = {
2246 0x80, spdy_version_ch_
, 0x00, 0x02,
2247 0x00, 0x00, 0x00, 0x32,
2248 0x00, 0x00, 0x00, 0x01,
2249 0x00, 0x00, 0x38, 0xea,
2250 0xdf, 0xa2, 0x51, 0xb2,
2251 0x62, 0x60, 0x62, 0x60,
2252 0x4e, 0x4a, 0x2c, 0x62,
2253 0x60, 0x06, 0x08, 0xa0,
2254 0xb4, 0xfc, 0x7c, 0x80,
2255 0x00, 0x62, 0x60, 0x4e,
2256 0xcb, 0xcf, 0x67, 0x60,
2257 0x06, 0x08, 0xa0, 0xa4,
2258 0xc4, 0x22, 0x80, 0x00,
2259 0x02, 0x00, 0x00, 0x00,
2262 const unsigned char kV3FrameData
[] = {
2263 0x80, spdy_version_ch_
, 0x00, 0x02,
2264 0x00, 0x00, 0x00, 0x31,
2265 0x00, 0x00, 0x00, 0x01,
2266 0x38, 0xea, 0xe3, 0xc6,
2267 0xa7, 0xc2, 0x02, 0xe5,
2268 0x0e, 0x50, 0xc2, 0x4b,
2269 0x4a, 0x04, 0xe5, 0x0b,
2270 0x66, 0x80, 0x00, 0x4a,
2271 0xcb, 0xcf, 0x07, 0x08,
2272 0x20, 0x10, 0x95, 0x96,
2273 0x9f, 0x0f, 0xa2, 0x00,
2274 0x02, 0x28, 0x29, 0xb1,
2275 0x08, 0x20, 0x80, 0x00,
2276 0x00, 0x00, 0x00, 0xff,
2279 SpdySynReplyIR
syn_reply(1);
2280 syn_reply
.SetHeader("bar", "foo");
2281 syn_reply
.SetHeader("foo", "bar");
2282 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2284 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2285 } else if (IsSpdy3()) {
2286 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2288 // Deflate compression doesn't apply to HPACK.
2292 #endif // !defined(USE_SYSTEM_ZLIB)
2294 TEST_P(SpdyFramerTest
, CreateRstStream
) {
2295 SpdyFramer
framer(spdy_version_
);
2298 const char kDescription
[] = "RST_STREAM frame";
2299 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2300 0x80, spdy_version_ch_
, 0x00, 0x03,
2301 0x00, 0x00, 0x00, 0x08,
2302 0x00, 0x00, 0x00, 0x01,
2303 0x00, 0x00, 0x00, 0x01,
2305 const unsigned char kV4FrameData
[] = {
2306 0x00, 0x07, 0x03, 0x00,
2307 0x00, 0x00, 0x00, 0x01,
2308 0x00, 0x00, 0x00, 0x01,
2311 SpdyRstStreamIR
rst_stream(1, RST_STREAM_PROTOCOL_ERROR
, "RST");
2312 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2314 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2316 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2321 const char kDescription
[] = "RST_STREAM frame with max stream ID";
2322 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2323 0x80, spdy_version_ch_
, 0x00, 0x03,
2324 0x00, 0x00, 0x00, 0x08,
2325 0x7f, 0xff, 0xff, 0xff,
2326 0x00, 0x00, 0x00, 0x01,
2328 const unsigned char kV4FrameData
[] = {
2329 0x00, 0x04, 0x03, 0x00,
2330 0x7f, 0xff, 0xff, 0xff,
2331 0x00, 0x00, 0x00, 0x01,
2333 SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2334 RST_STREAM_PROTOCOL_ERROR
,
2336 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2338 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2340 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2345 const char kDescription
[] = "RST_STREAM frame with max status code";
2346 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2347 0x80, spdy_version_ch_
, 0x00, 0x03,
2348 0x00, 0x00, 0x00, 0x08,
2349 0x7f, 0xff, 0xff, 0xff,
2350 0x00, 0x00, 0x00, 0x06,
2352 const unsigned char kV4FrameData
[] = {
2353 0x00, 0x04, 0x03, 0x00,
2354 0x7f, 0xff, 0xff, 0xff,
2355 0x00, 0x00, 0x00, 0x06,
2357 SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2358 RST_STREAM_INTERNAL_ERROR
,
2360 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2362 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2364 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2369 TEST_P(SpdyFramerTest
, CreateSettings
) {
2370 SpdyFramer
framer(spdy_version_
);
2373 const char kDescription
[] = "Network byte order SETTINGS frame";
2375 const unsigned char kV2FrameData
[] = {
2376 0x80, spdy_version_ch_
, 0x00, 0x04,
2377 0x00, 0x00, 0x00, 0x0c,
2378 0x00, 0x00, 0x00, 0x01,
2379 0x07, 0x00, 0x00, 0x01,
2380 0x0a, 0x0b, 0x0c, 0x0d,
2382 const unsigned char kV3FrameData
[] = {
2383 0x80, spdy_version_ch_
, 0x00, 0x04,
2384 0x00, 0x00, 0x00, 0x0c,
2385 0x00, 0x00, 0x00, 0x01,
2386 0x01, 0x00, 0x00, 0x07,
2387 0x0a, 0x0b, 0x0c, 0x0d,
2389 const unsigned char kV4FrameData
[] = {
2390 0x00, 0x05, 0x04, 0x00,
2391 0x00, 0x00, 0x00, 0x00,
2392 0x04, 0x0a, 0x0b, 0x0c,
2396 uint32 kValue
= 0x0a0b0c0d;
2397 SpdySettingsIR settings_ir
;
2399 SpdySettingsFlags kFlags
= static_cast<SpdySettingsFlags
>(0x01);
2400 SpdySettingsIds kId
= SETTINGS_INITIAL_WINDOW_SIZE
;
2401 SettingsMap settings
;
2402 settings
[kId
] = SettingsFlagsAndValue(kFlags
, kValue
);
2403 EXPECT_EQ(kFlags
, settings
[kId
].first
);
2404 EXPECT_EQ(kValue
, settings
[kId
].second
);
2405 settings_ir
.AddSetting(kId
,
2406 kFlags
& SETTINGS_FLAG_PLEASE_PERSIST
,
2407 kFlags
& SETTINGS_FLAG_PERSISTED
,
2410 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2412 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2413 } else if (IsSpdy3()) {
2414 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2416 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2421 const char kDescription
[] = "Basic SETTINGS frame";
2423 const unsigned char kV2FrameData
[] = {
2424 0x80, spdy_version_ch_
, 0x00, 0x04,
2425 0x00, 0x00, 0x00, 0x24,
2426 0x00, 0x00, 0x00, 0x04,
2427 0x01, 0x00, 0x00, 0x00, // 1st Setting
2428 0x00, 0x00, 0x00, 0x05,
2429 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2430 0x00, 0x00, 0x00, 0x06,
2431 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2432 0x00, 0x00, 0x00, 0x07,
2433 0x04, 0x00, 0x00, 0x00, // 4th Setting
2434 0x00, 0x00, 0x00, 0x08,
2436 const unsigned char kV3FrameData
[] = {
2437 0x80, spdy_version_ch_
, 0x00, 0x04,
2438 0x00, 0x00, 0x00, 0x24,
2439 0x00, 0x00, 0x00, 0x04,
2440 0x00, 0x00, 0x00, 0x01, // 1st Setting
2441 0x00, 0x00, 0x00, 0x05,
2442 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2443 0x00, 0x00, 0x00, 0x06,
2444 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2445 0x00, 0x00, 0x00, 0x07,
2446 0x00, 0x00, 0x00, 0x04, // 4th Setting
2447 0x00, 0x00, 0x00, 0x08,
2449 // These end up seemingly out of order because of the way that our internal
2450 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2452 const unsigned char kV4FrameData
[] = {
2453 0x00, 0x14, 0x04, 0x00,
2454 0x00, 0x00, 0x00, 0x00,
2455 0x03, // 3rd Setting
2456 0x00, 0x00, 0x00, 0x07,
2457 0x04, // 4th Setting
2458 0x00, 0x00, 0x00, 0x08,
2459 0x01, // 1st Setting
2460 0x00, 0x00, 0x00, 0x05,
2461 0x02, // 2nd Setting
2462 0x00, 0x00, 0x00, 0x06,
2465 SpdySettingsIR settings_ir
;
2466 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
2470 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 2),
2474 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 3),
2478 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 4),
2482 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2485 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2486 } else if (IsSpdy3()) {
2487 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2489 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2494 const char kDescription
[] = "Empty SETTINGS frame";
2496 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2497 0x80, spdy_version_ch_
, 0x00, 0x04,
2498 0x00, 0x00, 0x00, 0x04,
2499 0x00, 0x00, 0x00, 0x00,
2501 const unsigned char kV4FrameData
[] = {
2502 0x00, 0x00, 0x04, 0x00,
2503 0x00, 0x00, 0x00, 0x00,
2505 SpdySettingsIR settings_ir
;
2506 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2508 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2510 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2515 TEST_P(SpdyFramerTest
, CreatePingFrame
) {
2516 SpdyFramer
framer(spdy_version_
);
2519 const char kDescription
[] = "PING frame";
2520 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2521 0x80, spdy_version_ch_
, 0x00, 0x06,
2522 0x00, 0x00, 0x00, 0x04,
2523 0x12, 0x34, 0x56, 0x78,
2525 const unsigned char kV4FrameData
[] = {
2526 0x00, 0x08, 0x06, 0x00,
2527 0x00, 0x00, 0x00, 0x00,
2528 0x12, 0x34, 0x56, 0x78,
2529 0x9a, 0xbc, 0xde, 0xff,
2531 const unsigned char kV4FrameDataWithAck
[] = {
2532 0x00, 0x08, 0x06, 0x01,
2533 0x00, 0x00, 0x00, 0x00,
2534 0x12, 0x34, 0x56, 0x78,
2535 0x9a, 0xbc, 0xde, 0xff,
2537 scoped_ptr
<SpdyFrame
> frame
;
2539 const SpdyPingId kPingId
= 0x123456789abcdeffULL
;
2540 SpdyPingIR
ping_ir(kPingId
);
2541 // Tests SpdyPingIR when the ping is not an ack.
2542 ASSERT_FALSE(ping_ir
.is_ack());
2543 frame
.reset(framer
.SerializePing(ping_ir
));
2544 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2546 // Tests SpdyPingIR when the ping is an ack.
2547 ping_ir
.set_is_ack(true);
2548 frame
.reset(framer
.SerializePing(ping_ir
));
2549 CompareFrame(kDescription
, *frame
,
2550 kV4FrameDataWithAck
, arraysize(kV4FrameDataWithAck
));
2553 frame
.reset(framer
.SerializePing(SpdyPingIR(0x12345678ull
)));
2554 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2559 TEST_P(SpdyFramerTest
, CreateGoAway
) {
2560 SpdyFramer
framer(spdy_version_
);
2563 const char kDescription
[] = "GOAWAY frame";
2564 const unsigned char kV2FrameData
[] = {
2565 0x80, spdy_version_ch_
, 0x00, 0x07,
2566 0x00, 0x00, 0x00, 0x04,
2567 0x00, 0x00, 0x00, 0x00, // Stream Id
2569 const unsigned char kV3FrameData
[] = {
2570 0x80, spdy_version_ch_
, 0x00, 0x07,
2571 0x00, 0x00, 0x00, 0x08,
2572 0x00, 0x00, 0x00, 0x00, // Stream Id
2573 0x00, 0x00, 0x00, 0x00, // Status
2575 const unsigned char kV4FrameData
[] = {
2576 0x00, 0x0a, 0x07, 0x00,
2577 0x00, 0x00, 0x00, 0x00,
2578 0x00, 0x00, 0x00, 0x00, // Stream id
2579 0x00, 0x00, 0x00, 0x00, // Status
2580 0x47, 0x41, // Opaque Description
2582 SpdyGoAwayIR
goaway_ir(0, GOAWAY_OK
, "GA");
2583 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2585 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2586 } else if (IsSpdy3()) {
2587 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2589 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2594 const char kDescription
[] = "GOAWAY frame with max stream ID, status";
2595 const unsigned char kV2FrameData
[] = {
2596 0x80, spdy_version_ch_
, 0x00, 0x07,
2597 0x00, 0x00, 0x00, 0x04,
2598 0x7f, 0xff, 0xff, 0xff, // Stream Id
2600 const unsigned char kV3FrameData
[] = {
2601 0x80, spdy_version_ch_
, 0x00, 0x07,
2602 0x00, 0x00, 0x00, 0x08,
2603 0x7f, 0xff, 0xff, 0xff, // Stream Id
2604 0x00, 0x00, 0x00, 0x02, // Status
2606 const unsigned char kV4FrameData
[] = {
2607 0x00, 0x0a, 0x07, 0x00,
2608 0x00, 0x00, 0x00, 0x00,
2609 0x7f, 0xff, 0xff, 0xff, // Stream Id
2610 0x00, 0x00, 0x00, 0x02, // Status
2611 0x47, 0x41, // Opaque Description
2613 SpdyGoAwayIR
goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR
, "GA");
2614 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2616 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2617 } else if (IsSpdy3()) {
2618 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2620 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2625 TEST_P(SpdyFramerTest
, CreateHeadersUncompressed
) {
2626 SpdyFramer
framer(spdy_version_
);
2627 framer
.set_enable_compression(false);
2630 const char kDescription
[] = "HEADERS frame, no FIN";
2632 const unsigned char kV2FrameData
[] = {
2633 0x80, spdy_version_ch_
, 0x00, 0x08,
2634 0x00, 0x00, 0x00, 0x1C,
2635 0x00, 0x00, 0x00, 0x01,
2636 0x00, 0x00, 0x00, 0x02,
2637 0x00, 0x03, 'b', 'a',
2638 'r', 0x00, 0x03, 'f',
2639 'o', 'o', 0x00, 0x03,
2640 'f', 'o', 'o', 0x00,
2643 const unsigned char kV3FrameData
[] = {
2644 0x80, spdy_version_ch_
, 0x00, 0x08,
2645 0x00, 0x00, 0x00, 0x24,
2646 0x00, 0x00, 0x00, 0x01,
2647 0x00, 0x00, 0x00, 0x02,
2648 0x00, 0x00, 0x00, 0x03,
2649 'b', 'a', 'r', 0x00,
2650 0x00, 0x00, 0x03, 'f',
2651 'o', 'o', 0x00, 0x00,
2652 0x00, 0x03, 'f', 'o',
2653 'o', 0x00, 0x00, 0x00,
2656 const unsigned char kV4FrameData
[] = {
2657 0x00, 0x12, 0x01, 0x04, // Headers: END_HEADERS
2658 0x00, 0x00, 0x00, 0x01, // Stream 1
2659 0x00, 0x03, 0x62, 0x61, // @.ba
2660 0x72, 0x03, 0x66, 0x6f, // r.fo
2661 0x6f, 0x00, 0x03, 0x66, // o@.f
2662 0x6f, 0x6f, 0x03, 0x62, // oo.b
2665 SpdyHeadersIR
headers_ir(1);
2666 headers_ir
.SetHeader("bar", "foo");
2667 headers_ir
.SetHeader("foo", "bar");
2668 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2670 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2671 } else if (IsSpdy3()) {
2672 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2674 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2679 const char kDescription
[] =
2680 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2682 const unsigned char kV2FrameData
[] = {
2683 0x80, spdy_version_ch_
, 0x00, 0x08,
2684 0x01, 0x00, 0x00, 0x19,
2685 0x7f, 0xff, 0xff, 0xff,
2686 0x00, 0x00, 0x00, 0x02,
2687 0x00, 0x00, 0x00, 0x03,
2688 'f', 'o', 'o', 0x00,
2689 0x03, 'f', 'o', 'o',
2690 0x00, 0x03, 'b', 'a',
2693 const unsigned char kV3FrameData
[] = {
2694 0x80, spdy_version_ch_
, 0x00, 0x08,
2695 0x01, 0x00, 0x00, 0x21,
2696 0x7f, 0xff, 0xff, 0xff,
2697 0x00, 0x00, 0x00, 0x02,
2698 0x00, 0x00, 0x00, 0x00,
2699 0x00, 0x00, 0x00, 0x03,
2700 'f', 'o', 'o', 0x00,
2701 0x00, 0x00, 0x03, 'f',
2702 'o', 'o', 0x00, 0x00,
2703 0x00, 0x03, 'b', 'a',
2706 const unsigned char kV4FrameData
[] = {
2707 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2708 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2709 0x00, 0x00, 0x03, 0x66, // @..f
2710 0x6f, 0x6f, 0x00, 0x03, // oo@.
2711 0x66, 0x6f, 0x6f, 0x03, // foo.
2712 0x62, 0x61, 0x72, // bar
2714 SpdyHeadersIR
headers_ir(0x7fffffff);
2715 headers_ir
.set_fin(true);
2716 headers_ir
.SetHeader("", "foo");
2717 headers_ir
.SetHeader("foo", "bar");
2718 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2720 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2721 } else if (IsSpdy3()) {
2722 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2724 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2729 const char kDescription
[] =
2730 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2732 const unsigned char kV2FrameData
[] = {
2733 0x80, spdy_version_ch_
, 0x00, 0x08,
2734 0x01, 0x00, 0x00, 0x19,
2735 0x7f, 0xff, 0xff, 0xff,
2736 0x00, 0x00, 0x00, 0x02,
2737 0x00, 0x03, 'b', 'a',
2738 'r', 0x00, 0x03, 'f',
2739 'o', 'o', 0x00, 0x03,
2740 'f', 'o', 'o', 0x00,
2743 const unsigned char kV3FrameData
[] = {
2744 0x80, spdy_version_ch_
, 0x00, 0x08,
2745 0x01, 0x00, 0x00, 0x21,
2746 0x7f, 0xff, 0xff, 0xff,
2747 0x00, 0x00, 0x00, 0x02,
2748 0x00, 0x00, 0x00, 0x03,
2749 'b', 'a', 'r', 0x00,
2750 0x00, 0x00, 0x03, 'f',
2751 'o', 'o', 0x00, 0x00,
2752 0x00, 0x03, 'f', 'o',
2753 'o', 0x00, 0x00, 0x00,
2756 const unsigned char kV4FrameData
[] = {
2757 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2758 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2759 0x00, 0x03, 0x62, 0x61, // @.ba
2760 0x72, 0x03, 0x66, 0x6f, // r.fo
2761 0x6f, 0x00, 0x03, 0x66, // o@.f
2762 0x6f, 0x6f, 0x00, // oo.
2764 SpdyHeadersIR
headers_ir(0x7fffffff);
2765 headers_ir
.set_fin(true);
2766 headers_ir
.SetHeader("bar", "foo");
2767 headers_ir
.SetHeader("foo", "");
2768 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2770 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2771 } else if (IsSpdy3()) {
2772 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2774 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2779 // TODO(phajdan.jr): Clean up after we no longer need
2780 // to workaround http://crbug.com/139744.
2781 #if !defined(USE_SYSTEM_ZLIB)
2782 TEST_P(SpdyFramerTest
, CreateHeadersCompressed
) {
2783 SpdyFramer
framer(spdy_version_
);
2784 framer
.set_enable_compression(true);
2787 const char kDescription
[] = "HEADERS frame, no FIN";
2789 const unsigned char kV2FrameData
[] = {
2790 0x80, spdy_version_ch_
, 0x00, 0x08,
2791 0x00, 0x00, 0x00, 0x32,
2792 0x00, 0x00, 0x00, 0x01,
2793 0x00, 0x00, 0x38, 0xea,
2794 0xdf, 0xa2, 0x51, 0xb2,
2795 0x62, 0x60, 0x62, 0x60,
2796 0x4e, 0x4a, 0x2c, 0x62,
2797 0x60, 0x06, 0x08, 0xa0,
2798 0xb4, 0xfc, 0x7c, 0x80,
2799 0x00, 0x62, 0x60, 0x4e,
2800 0xcb, 0xcf, 0x67, 0x60,
2801 0x06, 0x08, 0xa0, 0xa4,
2802 0xc4, 0x22, 0x80, 0x00,
2803 0x02, 0x00, 0x00, 0x00,
2806 const unsigned char kV3FrameData
[] = {
2807 0x80, spdy_version_ch_
, 0x00, 0x08,
2808 0x00, 0x00, 0x00, 0x31,
2809 0x00, 0x00, 0x00, 0x01,
2810 0x38, 0xea, 0xe3, 0xc6,
2811 0xa7, 0xc2, 0x02, 0xe5,
2812 0x0e, 0x50, 0xc2, 0x4b,
2813 0x4a, 0x04, 0xe5, 0x0b,
2814 0x66, 0x80, 0x00, 0x4a,
2815 0xcb, 0xcf, 0x07, 0x08,
2816 0x20, 0x10, 0x95, 0x96,
2817 0x9f, 0x0f, 0xa2, 0x00,
2818 0x02, 0x28, 0x29, 0xb1,
2819 0x08, 0x20, 0x80, 0x00,
2820 0x00, 0x00, 0x00, 0xff,
2823 SpdyHeadersIR
headers_ir(1);
2824 headers_ir
.SetHeader("bar", "foo");
2825 headers_ir
.SetHeader("foo", "bar");
2826 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2828 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2829 } else if (IsSpdy3()) {
2830 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2832 // Deflate compression doesn't apply to HPACK.
2836 #endif // !defined(USE_SYSTEM_ZLIB)
2838 TEST_P(SpdyFramerTest
, CreateWindowUpdate
) {
2839 SpdyFramer
framer(spdy_version_
);
2842 const char kDescription
[] = "WINDOW_UPDATE frame";
2843 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2844 0x80, spdy_version_ch_
, 0x00, 0x09,
2845 0x00, 0x00, 0x00, 0x08,
2846 0x00, 0x00, 0x00, 0x01,
2847 0x00, 0x00, 0x00, 0x01,
2849 const unsigned char kV4FrameData
[] = {
2850 0x00, 0x04, 0x08, 0x00,
2851 0x00, 0x00, 0x00, 0x01,
2852 0x00, 0x00, 0x00, 0x01,
2854 scoped_ptr
<SpdyFrame
> frame(
2855 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
2857 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2859 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2864 const char kDescription
[] = "WINDOW_UPDATE frame with max stream ID";
2865 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2866 0x80, spdy_version_ch_
, 0x00, 0x09,
2867 0x00, 0x00, 0x00, 0x08,
2868 0x7f, 0xff, 0xff, 0xff,
2869 0x00, 0x00, 0x00, 0x01,
2871 const unsigned char kV4FrameData
[] = {
2872 0x00, 0x04, 0x08, 0x00,
2873 0x7f, 0xff, 0xff, 0xff,
2874 0x00, 0x00, 0x00, 0x01,
2876 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
2877 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2879 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2881 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2886 const char kDescription
[] = "WINDOW_UPDATE frame with max window delta";
2887 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2888 0x80, spdy_version_ch_
, 0x00, 0x09,
2889 0x00, 0x00, 0x00, 0x08,
2890 0x00, 0x00, 0x00, 0x01,
2891 0x7f, 0xff, 0xff, 0xff,
2893 const unsigned char kV4FrameData
[] = {
2894 0x00, 0x04, 0x08, 0x00,
2895 0x00, 0x00, 0x00, 0x01,
2896 0x7f, 0xff, 0xff, 0xff,
2898 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
2899 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2901 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2903 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2908 TEST_P(SpdyFramerTest
, SerializeBlocked
) {
2909 if (spdy_version_
<= SPDY3
) {
2913 SpdyFramer
framer(spdy_version_
);
2915 const char kDescription
[] = "BLOCKED frame";
2916 const unsigned char kType
= static_cast<unsigned char>(
2917 SpdyConstants::SerializeFrameType(spdy_version_
, BLOCKED
));
2918 const unsigned char kFrameData
[] = {
2919 0x00, 0x00, kType
, 0x00,
2920 0x00, 0x00, 0x00, 0x00,
2922 SpdyBlockedIR
blocked_ir(0);
2923 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
2924 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
2927 TEST_P(SpdyFramerTest
, CreateBlocked
) {
2928 if (spdy_version_
<= SPDY3
) {
2932 SpdyFramer
framer(spdy_version_
);
2934 const char kDescription
[] = "BLOCKED frame";
2935 const SpdyStreamId kStreamId
= 3;
2937 scoped_ptr
<SpdySerializedFrame
> frame_serialized(
2938 framer
.SerializeBlocked(SpdyBlockedIR(kStreamId
)));
2939 SpdyBlockedIR
blocked_ir(kStreamId
);
2940 scoped_ptr
<SpdySerializedFrame
> frame_created(
2941 framer
.SerializeFrame(blocked_ir
));
2943 CompareFrames(kDescription
, *frame_serialized
, *frame_created
);
2946 TEST_P(SpdyFramerTest
, CreatePushPromiseUncompressed
) {
2947 if (spdy_version_
<= SPDY3
) {
2951 SpdyFramer
framer(spdy_version_
);
2952 framer
.set_enable_compression(false);
2953 const char kDescription
[] = "PUSH_PROMISE frame";
2955 const unsigned char kFrameData
[] = {
2956 0x00, 0x16, 0x05, 0x04, // PUSH_PROMISE: END_HEADERS
2957 0x00, 0x00, 0x00, 0x2a, // Stream 42
2958 0x00, 0x00, 0x00, 0x39, // Promised stream 57
2959 0x00, 0x03, 0x62, 0x61, // @.ba
2960 0x72, 0x03, 0x66, 0x6f, // r.fo
2961 0x6f, 0x00, 0x03, 0x66, // o@.f
2962 0x6f, 0x6f, 0x03, 0x62, // oo.b
2966 SpdyPushPromiseIR
push_promise(42, 57);
2967 push_promise
.SetHeader("bar", "foo");
2968 push_promise
.SetHeader("foo", "bar");
2969 scoped_ptr
<SpdySerializedFrame
> frame(
2970 framer
.SerializePushPromise(push_promise
));
2971 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
2974 TEST_P(SpdyFramerTest
, CreateAltSvc
) {
2975 if (spdy_version_
<= SPDY3
) {
2979 SpdyFramer
framer(spdy_version_
);
2981 const char kDescription
[] = "ALTSVC frame";
2982 const unsigned char kType
= static_cast<unsigned char>(
2983 SpdyConstants::SerializeFrameType(spdy_version_
, ALTSVC
));
2984 const unsigned char kFrameData
[] = {
2985 0x00, 0x17, kType
, 0x00,
2986 0x00, 0x00, 0x00, 0x03,
2987 0x00, 0x00, 0x00, 0x05,
2988 0x01, 0xbb, 0x00, 0x04, // Port = 443
2989 'p', 'i', 'd', '1', // Protocol-ID
2990 0x04, 'h', 'o', 's',
2994 SpdyAltSvcIR
altsvc_ir(3);
2995 altsvc_ir
.set_max_age(5);
2996 altsvc_ir
.set_port(443);
2997 altsvc_ir
.set_protocol_id("pid1");
2998 altsvc_ir
.set_host("host");
2999 altsvc_ir
.set_origin("origin");
3000 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
3001 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3004 TEST_P(SpdyFramerTest
, ReadCompressedSynStreamHeaderBlock
) {
3005 SpdyFramer
framer(spdy_version_
);
3006 SpdySynStreamIR
syn_stream(1);
3007 syn_stream
.set_priority(1);
3008 syn_stream
.SetHeader("aa", "vv");
3009 syn_stream
.SetHeader("bb", "ww");
3010 SpdyHeaderBlock headers
= syn_stream
.name_value_block();
3011 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3012 EXPECT_TRUE(control_frame
.get() != NULL
);
3013 TestSpdyVisitor
visitor(spdy_version_
);
3014 visitor
.use_compression_
= true;
3015 visitor
.SimulateInFramer(
3016 reinterpret_cast<unsigned char*>(control_frame
->data()),
3017 control_frame
->size());
3018 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3019 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3022 TEST_P(SpdyFramerTest
, ReadCompressedSynReplyHeaderBlock
) {
3023 SpdyFramer
framer(spdy_version_
);
3024 SpdySynReplyIR
syn_reply(1);
3025 syn_reply
.SetHeader("alpha", "beta");
3026 syn_reply
.SetHeader("gamma", "delta");
3027 SpdyHeaderBlock headers
= syn_reply
.name_value_block();
3028 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynReply(syn_reply
));
3029 EXPECT_TRUE(control_frame
.get() != NULL
);
3030 TestSpdyVisitor
visitor(spdy_version_
);
3031 visitor
.use_compression_
= true;
3032 visitor
.SimulateInFramer(
3033 reinterpret_cast<unsigned char*>(control_frame
->data()),
3034 control_frame
->size());
3036 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
3037 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3039 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
3040 EXPECT_EQ(0, visitor
.headers_frame_count_
);
3042 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3045 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlock
) {
3046 SpdyFramer
framer(spdy_version_
);
3047 SpdyHeadersIR
headers_ir(1);
3048 headers_ir
.SetHeader("alpha", "beta");
3049 headers_ir
.SetHeader("gamma", "delta");
3050 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
3051 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
3052 EXPECT_TRUE(control_frame
.get() != NULL
);
3053 TestSpdyVisitor
visitor(spdy_version_
);
3054 visitor
.use_compression_
= true;
3055 visitor
.SimulateInFramer(
3056 reinterpret_cast<unsigned char*>(control_frame
->data()),
3057 control_frame
->size());
3058 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3059 // control_frame_header_data_count_ depends on the random sequence
3060 // produced by rand(), so adding, removing or running single tests
3061 // alters this value. The best we can do is assert that it happens
3063 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
3064 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3065 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3066 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3069 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlockWithHalfClose
) {
3070 SpdyFramer
framer(spdy_version_
);
3071 SpdyHeadersIR
headers_ir(1);
3072 headers_ir
.set_fin(true);
3073 headers_ir
.SetHeader("alpha", "beta");
3074 headers_ir
.SetHeader("gamma", "delta");
3075 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
3076 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
3077 EXPECT_TRUE(control_frame
.get() != NULL
);
3078 TestSpdyVisitor
visitor(spdy_version_
);
3079 visitor
.use_compression_
= true;
3080 visitor
.SimulateInFramer(
3081 reinterpret_cast<unsigned char*>(control_frame
->data()),
3082 control_frame
->size());
3083 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3084 // control_frame_header_data_count_ depends on the random sequence
3085 // produced by rand(), so adding, removing or running single tests
3086 // alters this value. The best we can do is assert that it happens
3088 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
3089 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3090 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
3091 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3094 TEST_P(SpdyFramerTest
, ControlFrameAtMaxSizeLimit
) {
3095 if (spdy_version_
> SPDY3
) {
3096 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3099 // First find the size of the header value in order to just reach the control
3101 SpdyFramer
framer(spdy_version_
);
3102 framer
.set_enable_compression(false);
3103 SpdySynStreamIR
syn_stream(1);
3104 syn_stream
.set_priority(1);
3105 syn_stream
.SetHeader("aa", "");
3106 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3107 const size_t kBigValueSize
=
3108 framer
.GetControlFrameBufferMaxSize() - control_frame
->size();
3110 // Create a frame at exactly that size.
3111 string
big_value(kBigValueSize
, 'x');
3112 syn_stream
.SetHeader("aa", big_value
);
3113 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
3114 EXPECT_TRUE(control_frame
.get() != NULL
);
3115 EXPECT_EQ(framer
.GetControlFrameBufferMaxSize(), control_frame
->size());
3117 TestSpdyVisitor
visitor(spdy_version_
);
3118 visitor
.SimulateInFramer(
3119 reinterpret_cast<unsigned char*>(control_frame
->data()),
3120 control_frame
->size());
3121 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3122 EXPECT_EQ(0, visitor
.error_count_
);
3123 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3124 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3125 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3126 EXPECT_LT(kBigValueSize
, visitor
.header_buffer_length_
);
3129 TEST_P(SpdyFramerTest
, ControlFrameTooLarge
) {
3130 if (spdy_version_
> SPDY3
) {
3131 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3134 // First find the size of the header value in order to just reach the control
3136 SpdyFramer
framer(spdy_version_
);
3137 framer
.set_enable_compression(false);
3138 SpdySynStreamIR
syn_stream(1);
3139 syn_stream
.SetHeader("aa", "");
3140 syn_stream
.set_priority(1);
3141 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3142 const size_t kBigValueSize
=
3143 framer
.GetControlFrameBufferMaxSize() - control_frame
->size() + 1;
3145 // Create a frame at exatly that size.
3146 string
big_value(kBigValueSize
, 'x');
3147 syn_stream
.SetHeader("aa", big_value
);
3148 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3149 // neither support that in Chromium, nor do we use the same DFATAL (see
3150 // SpdyFrameBuilder::WriteFramePrefix()).
3151 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
3153 EXPECT_TRUE(control_frame
.get() != NULL
);
3154 EXPECT_EQ(framer
.GetControlFrameBufferMaxSize() + 1,
3155 control_frame
->size());
3157 TestSpdyVisitor
visitor(spdy_version_
);
3158 visitor
.SimulateInFramer(
3159 reinterpret_cast<unsigned char*>(control_frame
->data()),
3160 control_frame
->size());
3161 EXPECT_FALSE(visitor
.header_buffer_valid_
);
3162 EXPECT_EQ(1, visitor
.error_count_
);
3163 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
3164 visitor
.framer_
.error_code())
3165 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3166 EXPECT_EQ(0, visitor
.syn_frame_count_
);
3167 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3170 TEST_P(SpdyFramerTest
, TooLargeHeadersFrameUsesContinuation
) {
3171 if (spdy_version_
<= SPDY3
) {
3174 SpdyFramer
framer(spdy_version_
);
3175 framer
.set_enable_compression(false);
3176 SpdyHeadersIR
headers(1);
3178 // Exact payload length will change with HPACK, but this should be long
3179 // enough to cause an overflow.
3180 const size_t kBigValueSize
= framer
.GetControlFrameBufferMaxSize();
3181 string
big_value(kBigValueSize
, 'x');
3182 headers
.SetHeader("aa", big_value
);
3183 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers
));
3184 EXPECT_TRUE(control_frame
.get() != NULL
);
3185 EXPECT_GT(control_frame
->size(), framer
.GetControlFrameBufferMaxSize());
3187 TestSpdyVisitor
visitor(spdy_version_
);
3188 visitor
.SimulateInFramer(
3189 reinterpret_cast<unsigned char*>(control_frame
->data()),
3190 control_frame
->size());
3191 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3192 EXPECT_EQ(0, visitor
.error_count_
);
3193 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3194 EXPECT_EQ(1, visitor
.continuation_count_
);
3195 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3198 TEST_P(SpdyFramerTest
, TooLargePushPromiseFrameUsesContinuation
) {
3199 if (spdy_version_
<= SPDY3
) {
3202 SpdyFramer
framer(spdy_version_
);
3203 framer
.set_enable_compression(false);
3204 SpdyPushPromiseIR
push_promise(1, 2);
3206 // Exact payload length will change with HPACK, but this should be long
3207 // enough to cause an overflow.
3208 const size_t kBigValueSize
= framer
.GetControlFrameBufferMaxSize();
3209 string
big_value(kBigValueSize
, 'x');
3210 push_promise
.SetHeader("aa", big_value
);
3211 scoped_ptr
<SpdyFrame
> control_frame(
3212 framer
.SerializePushPromise(push_promise
));
3213 EXPECT_TRUE(control_frame
.get() != NULL
);
3214 EXPECT_GT(control_frame
->size(), framer
.GetControlFrameBufferMaxSize());
3216 TestSpdyVisitor
visitor(spdy_version_
);
3217 visitor
.SimulateInFramer(
3218 reinterpret_cast<unsigned char*>(control_frame
->data()),
3219 control_frame
->size());
3220 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3221 EXPECT_EQ(0, visitor
.error_count_
);
3222 EXPECT_EQ(1, visitor
.push_promise_frame_count_
);
3223 EXPECT_EQ(1, visitor
.continuation_count_
);
3224 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3227 // Check that the framer stops delivering header data chunks once the visitor
3228 // declares it doesn't want any more. This is important to guard against
3229 // "zip bomb" types of attacks.
3230 TEST_P(SpdyFramerTest
, ControlFrameMuchTooLarge
) {
3231 const size_t kHeaderBufferChunks
= 4;
3232 const size_t kHeaderBufferSize
=
3233 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks
;
3234 const size_t kBigValueSize
= kHeaderBufferSize
* 2;
3235 string
big_value(kBigValueSize
, 'x');
3236 SpdyFramer
framer(spdy_version_
);
3237 SpdySynStreamIR
syn_stream(1);
3238 syn_stream
.set_priority(1);
3239 syn_stream
.set_fin(true);
3240 syn_stream
.SetHeader("aa", big_value
);
3241 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3242 EXPECT_TRUE(control_frame
.get() != NULL
);
3243 TestSpdyVisitor
visitor(spdy_version_
);
3244 visitor
.set_header_buffer_size(kHeaderBufferSize
);
3245 visitor
.use_compression_
= true;
3246 visitor
.SimulateInFramer(
3247 reinterpret_cast<unsigned char*>(control_frame
->data()),
3248 control_frame
->size());
3249 EXPECT_FALSE(visitor
.header_buffer_valid_
);
3250 EXPECT_EQ(1, visitor
.error_count_
);
3251 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
3252 visitor
.framer_
.error_code())
3253 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3255 // The framer should have stoped delivering chunks after the visitor
3256 // signaled "stop" by returning false from OnControlFrameHeaderData().
3258 // control_frame_header_data_count_ depends on the random sequence
3259 // produced by rand(), so adding, removing or running single tests
3260 // alters this value. The best we can do is assert that it happens
3261 // at least kHeaderBufferChunks + 1.
3262 EXPECT_LE(kHeaderBufferChunks
+ 1,
3263 static_cast<unsigned>(visitor
.control_frame_header_data_count_
));
3264 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
3266 // The framer should not have sent half-close to the visitor.
3267 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3270 TEST_P(SpdyFramerTest
, DecompressCorruptHeaderBlock
) {
3271 if (spdy_version_
> SPDY3
) {
3272 // Deflate compression doesn't apply to HPACK.
3275 SpdyFramer
framer(spdy_version_
);
3276 framer
.set_enable_compression(false);
3277 // Construct a SYN_STREAM control frame without compressing the header block,
3278 // and have the framer try to decompress it. This will cause the framer to
3279 // deal with a decompression error.
3280 SpdySynStreamIR
syn_stream(1);
3281 syn_stream
.set_priority(1);
3282 syn_stream
.SetHeader("aa", "alpha beta gamma delta");
3283 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3284 TestSpdyVisitor
visitor(spdy_version_
);
3285 visitor
.use_compression_
= true;
3286 visitor
.SimulateInFramer(
3287 reinterpret_cast<unsigned char*>(control_frame
->data()),
3288 control_frame
->size());
3289 EXPECT_EQ(1, visitor
.error_count_
);
3290 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE
, visitor
.framer_
.error_code())
3291 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3292 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3295 TEST_P(SpdyFramerTest
, ControlFrameSizesAreValidated
) {
3296 SpdyFramer
framer(spdy_version_
);
3297 // Create a GoAway frame that has a few extra bytes at the end.
3298 // We create enough overhead to overflow the framer's control frame buffer.
3299 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize
);
3300 const unsigned char length
= 1 + SpdyFramer::kControlFrameBufferSize
;
3301 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3302 0x80, spdy_version_ch_
, 0x00, 0x07,
3303 0x00, 0x00, 0x00, length
,
3304 0x00, 0x00, 0x00, 0x00, // Stream ID
3305 0x00, 0x00, 0x00, 0x00, // Status
3308 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3309 // since it may carry opaque data. Verify that minimal length is tested.
3310 const unsigned char less_than_min_length
=
3311 framer
.GetGoAwayMinimumSize() - framer
.GetControlFrameHeaderSize() - 1;
3312 const unsigned char kV4FrameData
[] = {
3313 0x00, static_cast<uint8
>(less_than_min_length
), 0x07, 0x00,
3314 0x00, 0x00, 0x00, 0x00,
3315 0x00, 0x00, 0x00, 0x00, // Stream Id
3316 0x00, 0x00, 0x00, 0x00, // Status
3318 const size_t pad_length
=
3319 length
+ framer
.GetControlFrameHeaderSize() -
3320 (IsSpdy4() ? sizeof(kV4FrameData
) : sizeof(kV3FrameData
));
3321 string
pad('A', pad_length
);
3322 TestSpdyVisitor
visitor(spdy_version_
);
3325 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3327 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3329 visitor
.SimulateInFramer(
3330 reinterpret_cast<const unsigned char*>(pad
.c_str()),
3333 EXPECT_EQ(1, visitor
.error_count_
); // This generated an error.
3334 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
3335 visitor
.framer_
.error_code())
3336 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3337 EXPECT_EQ(0, visitor
.goaway_count_
); // Frame not parsed.
3340 TEST_P(SpdyFramerTest
, ReadZeroLenSettingsFrame
) {
3341 SpdyFramer
framer(spdy_version_
);
3342 SpdySettingsIR settings_ir
;
3343 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3344 SetFrameLength(control_frame
.get(), 0, spdy_version_
);
3345 TestSpdyVisitor
visitor(spdy_version_
);
3346 visitor
.use_compression_
= false;
3347 visitor
.SimulateInFramer(
3348 reinterpret_cast<unsigned char*>(control_frame
->data()),
3349 framer
.GetControlFrameHeaderSize());
3350 if (spdy_version_
<= SPDY3
) {
3351 // Should generate an error, since zero-len settings frames are unsupported.
3352 EXPECT_EQ(1, visitor
.error_count_
);
3354 // Zero-len settings frames are permitted as of SPDY 4.
3355 EXPECT_EQ(0, visitor
.error_count_
);
3359 // Tests handling of SETTINGS frames with invalid length.
3360 TEST_P(SpdyFramerTest
, ReadBogusLenSettingsFrame
) {
3361 SpdyFramer
framer(spdy_version_
);
3362 SpdySettingsIR settings_ir
;
3364 // Add a setting to pad the frame so that we don't get a buffer overflow when
3365 // calling SimulateInFramer() below.
3366 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
,
3370 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3371 const size_t kNewLength
= 14;
3372 SetFrameLength(control_frame
.get(), kNewLength
, spdy_version_
);
3373 TestSpdyVisitor
visitor(spdy_version_
);
3374 visitor
.use_compression_
= false;
3375 visitor
.SimulateInFramer(
3376 reinterpret_cast<unsigned char*>(control_frame
->data()),
3377 framer
.GetControlFrameHeaderSize() + kNewLength
);
3378 // Should generate an error, since its not possible to have a
3379 // settings frame of length kNewLength.
3380 EXPECT_EQ(1, visitor
.error_count_
);
3383 // Tests handling of SETTINGS frames larger than the frame buffer size.
3384 TEST_P(SpdyFramerTest
, ReadLargeSettingsFrame
) {
3385 SpdyFramer
framer(spdy_version_
);
3386 SpdySettingsIR settings_ir
;
3387 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
3391 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 2),
3395 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 3),
3400 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3401 EXPECT_LT(SpdyFramer::kControlFrameBufferSize
,
3402 control_frame
->size());
3403 TestSpdyVisitor
visitor(spdy_version_
);
3404 visitor
.use_compression_
= false;
3406 // Read all at once.
3407 visitor
.SimulateInFramer(
3408 reinterpret_cast<unsigned char*>(control_frame
->data()),
3409 control_frame
->size());
3410 EXPECT_EQ(0, visitor
.error_count_
);
3411 EXPECT_EQ(3, visitor
.setting_count_
);
3412 if (spdy_version_
> SPDY3
) {
3413 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3416 // Read data in small chunks.
3417 size_t framed_data
= 0;
3418 size_t unframed_data
= control_frame
->size();
3419 size_t kReadChunkSize
= 5; // Read five bytes at a time.
3420 while (unframed_data
> 0) {
3421 size_t to_read
= min(kReadChunkSize
, unframed_data
);
3422 visitor
.SimulateInFramer(
3423 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
3425 unframed_data
-= to_read
;
3426 framed_data
+= to_read
;
3428 EXPECT_EQ(0, visitor
.error_count_
);
3429 EXPECT_EQ(3 * 2, visitor
.setting_count_
);
3430 if (spdy_version_
> SPDY3
) {
3431 EXPECT_EQ(2, visitor
.settings_ack_sent_
);
3435 // Tests handling of SETTINGS frame with duplicate entries.
3436 TEST_P(SpdyFramerTest
, ReadDuplicateSettings
) {
3437 SpdyFramer
framer(spdy_version_
);
3439 const unsigned char kV2FrameData
[] = {
3440 0x80, spdy_version_ch_
, 0x00, 0x04,
3441 0x00, 0x00, 0x00, 0x1C,
3442 0x00, 0x00, 0x00, 0x03,
3443 0x01, 0x00, 0x00, 0x00, // 1st Setting
3444 0x00, 0x00, 0x00, 0x02,
3445 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3446 0x00, 0x00, 0x00, 0x03,
3447 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3448 0x00, 0x00, 0x00, 0x03,
3450 const unsigned char kV3FrameData
[] = {
3451 0x80, spdy_version_ch_
, 0x00, 0x04,
3452 0x00, 0x00, 0x00, 0x1C,
3453 0x00, 0x00, 0x00, 0x03,
3454 0x00, 0x00, 0x00, 0x01, // 1st Setting
3455 0x00, 0x00, 0x00, 0x02,
3456 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3457 0x00, 0x00, 0x00, 0x03,
3458 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3459 0x00, 0x00, 0x00, 0x03,
3461 const unsigned char kV4FrameData
[] = {
3462 0x00, 0x0f, 0x04, 0x00,
3463 0x00, 0x00, 0x00, 0x00,
3464 0x01, // 1st Setting
3465 0x00, 0x00, 0x00, 0x02,
3466 0x01, // 2nd (duplicate) Setting
3467 0x00, 0x00, 0x00, 0x03,
3468 0x03, // 3rd (unprocessed) Setting
3469 0x00, 0x00, 0x00, 0x03,
3472 TestSpdyVisitor
visitor(spdy_version_
);
3473 visitor
.use_compression_
= false;
3475 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
3476 } else if (IsSpdy3()) {
3477 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3479 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3483 EXPECT_EQ(1, visitor
.setting_count_
);
3484 EXPECT_EQ(1, visitor
.error_count_
);
3486 // In SPDY 4+, duplicate settings are allowed;
3487 // each setting replaces the previous value for that setting.
3488 EXPECT_EQ(3, visitor
.setting_count_
);
3489 EXPECT_EQ(0, visitor
.error_count_
);
3490 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3494 // Tests handling of SETTINGS_COMPRESS_DATA.
3495 TEST_P(SpdyFramerTest
, AcceptSettingsCompressData
) {
3496 if (!IsSpdy4()) { return; }
3497 SpdyFramer
framer(spdy_version_
);
3499 const unsigned char kFrameData
[] = {
3500 0x00, 0x05, 0x04, 0x00,
3501 0x00, 0x00, 0x00, 0x00,
3502 0x05, 0x00, 0x00, 0x00,
3506 TestSpdyVisitor
visitor(spdy_version_
);
3507 visitor
.use_compression_
= false;
3508 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
3509 EXPECT_EQ(1, visitor
.setting_count_
);
3510 EXPECT_EQ(0, visitor
.error_count_
);
3513 // Tests handling of SETTINGS frame with entries out of order.
3514 TEST_P(SpdyFramerTest
, ReadOutOfOrderSettings
) {
3515 SpdyFramer
framer(spdy_version_
);
3517 const unsigned char kV2FrameData
[] = {
3518 0x80, spdy_version_ch_
, 0x00, 0x04,
3519 0x00, 0x00, 0x00, 0x1C,
3520 0x00, 0x00, 0x00, 0x03,
3521 0x02, 0x00, 0x00, 0x00, // 1st Setting
3522 0x00, 0x00, 0x00, 0x02,
3523 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
3524 0x00, 0x00, 0x00, 0x03,
3525 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3526 0x00, 0x00, 0x00, 0x03,
3528 const unsigned char kV3FrameData
[] = {
3529 0x80, spdy_version_ch_
, 0x00, 0x04,
3530 0x00, 0x00, 0x00, 0x1C,
3531 0x00, 0x00, 0x00, 0x03,
3532 0x00, 0x00, 0x00, 0x02, // 1st Setting
3533 0x00, 0x00, 0x00, 0x02,
3534 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3535 0x00, 0x00, 0x00, 0x03,
3536 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3537 0x00, 0x00, 0x00, 0x03,
3539 const unsigned char kV4FrameData
[] = {
3540 0x00, 0x0f, 0x04, 0x00,
3541 0x00, 0x00, 0x00, 0x00,
3542 0x02, // 1st Setting
3543 0x00, 0x00, 0x00, 0x02,
3544 0x01, // 2nd (out of order) Setting
3545 0x00, 0x00, 0x00, 0x03,
3546 0x03, // 3rd (unprocessed) Setting
3547 0x00, 0x00, 0x00, 0x03,
3550 TestSpdyVisitor
visitor(spdy_version_
);
3551 visitor
.use_compression_
= false;
3553 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
3554 } else if (IsSpdy3()) {
3555 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3557 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3561 EXPECT_EQ(1, visitor
.setting_count_
);
3562 EXPECT_EQ(1, visitor
.error_count_
);
3564 // In SPDY 4+, settings are allowed in any order.
3565 EXPECT_EQ(3, visitor
.setting_count_
);
3566 EXPECT_EQ(0, visitor
.error_count_
);
3567 // EXPECT_EQ(1, visitor.settings_ack_count_);
3571 TEST_P(SpdyFramerTest
, ProcessSettingsAckFrame
) {
3572 if (spdy_version_
<= SPDY3
) {
3575 SpdyFramer
framer(spdy_version_
);
3577 const unsigned char kFrameData
[] = {
3578 0x00, 0x00, 0x04, 0x01,
3579 0x00, 0x00, 0x00, 0x00,
3582 TestSpdyVisitor
visitor(spdy_version_
);
3583 visitor
.use_compression_
= false;
3584 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
3586 EXPECT_EQ(0, visitor
.error_count_
);
3587 EXPECT_EQ(0, visitor
.setting_count_
);
3588 EXPECT_EQ(1, visitor
.settings_ack_received_
);
3592 TEST_P(SpdyFramerTest
, ProcessDataFrameWithPadding
) {
3593 if (spdy_version_
<= SPDY3
) {
3597 const int kPaddingLen
= 512; // So we get two bytes for padding length field.
3598 const char data_payload
[] = "hello";
3600 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
3601 SpdyFramer
framer(spdy_version_
);
3602 framer
.set_visitor(&visitor
);
3604 SpdyDataIR
data_ir(1, StringPiece(data_payload
, strlen(data_payload
)));
3605 data_ir
.set_padding_len(kPaddingLen
);
3606 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
3607 ASSERT_TRUE(frame
.get() != NULL
);
3609 int bytes_consumed
= 0;
3611 // Send the frame header.
3612 EXPECT_CALL(visitor
, OnDataFrameHeader(1,
3613 kPaddingLen
+ strlen(data_payload
),
3615 CHECK_EQ(8u, framer
.ProcessInput(frame
->data(), 8));
3616 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH
);
3617 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3618 bytes_consumed
+= 8;
3620 // Send the first byte of the padding length field.
3621 CHECK_EQ(1u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 1));
3622 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH
);
3623 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3624 bytes_consumed
+= 1;
3626 // Send the second byte of the padding length field.
3627 CHECK_EQ(1u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 1));
3628 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME
);
3629 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3630 bytes_consumed
+= 1;
3632 // Send the first two bytes of the data payload.
3633 EXPECT_CALL(visitor
, OnStreamFrameData(1, _
, 2, false));
3634 CHECK_EQ(2u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 2));
3635 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME
);
3636 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3637 bytes_consumed
+= 2;
3639 // Send the rest three bytes of the data payload.
3640 EXPECT_CALL(visitor
, OnStreamFrameData(1, _
, 3, false));
3641 CHECK_EQ(3u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 3));
3642 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_CONSUME_PADDING
);
3643 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3644 bytes_consumed
+= 3;
3646 // Send the first 100 bytes of the padding payload.
3647 EXPECT_CALL(visitor
, OnStreamFrameData(1, NULL
, 100, false));
3648 CHECK_EQ(100u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 100));
3649 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_CONSUME_PADDING
);
3650 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3651 bytes_consumed
+= 100;
3653 // Send rest of the padding payload.
3654 EXPECT_CALL(visitor
, OnStreamFrameData(1, NULL
, 410, false));
3655 CHECK_EQ(410u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 410));
3656 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_RESET
);
3657 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
3660 TEST_P(SpdyFramerTest
, ReadWindowUpdate
) {
3661 SpdyFramer
framer(spdy_version_
);
3662 scoped_ptr
<SpdyFrame
> control_frame(
3663 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3664 TestSpdyVisitor
visitor(spdy_version_
);
3665 visitor
.SimulateInFramer(
3666 reinterpret_cast<unsigned char*>(control_frame
->data()),
3667 control_frame
->size());
3668 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
3669 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
3672 TEST_P(SpdyFramerTest
, ReceiveCredentialFrame
) {
3676 SpdyFramer
framer(spdy_version_
);
3677 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3678 0x80, spdy_version_ch_
, 0x00, 0x0A,
3679 0x00, 0x00, 0x00, 0x33,
3680 0x00, 0x03, 0x00, 0x00,
3681 0x00, 0x05, 'p', 'r',
3682 'o', 'o', 'f', 0x00,
3683 0x00, 0x00, 0x06, 'a',
3685 't', 0x00, 0x00, 0x00,
3686 0x0C, 'a', 'n', 'o',
3689 't', 0x00, 0x00, 0x00,
3690 0x0A, 'f', 'i', 'n',
3694 TestSpdyVisitor
visitor(spdy_version_
);
3695 visitor
.use_compression_
= false;
3696 visitor
.SimulateInFramer(kV3FrameData
, arraysize(kV3FrameData
));
3697 EXPECT_EQ(0, visitor
.error_count_
);
3700 TEST_P(SpdyFramerTest
, ReadCredentialFrameFollowedByAnotherFrame
) {
3704 SpdyFramer
framer(spdy_version_
);
3705 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3706 0x80, spdy_version_ch_
, 0x00, 0x0A,
3707 0x00, 0x00, 0x00, 0x33,
3708 0x00, 0x03, 0x00, 0x00,
3709 0x00, 0x05, 'p', 'r',
3710 'o', 'o', 'f', 0x00,
3711 0x00, 0x00, 0x06, 'a',
3713 't', 0x00, 0x00, 0x00,
3714 0x0C, 'a', 'n', 'o',
3717 't', 0x00, 0x00, 0x00,
3718 0x0A, 'f', 'i', 'n',
3722 TestSpdyVisitor
visitor(spdy_version_
);
3723 visitor
.use_compression_
= false;
3724 string
multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData
),
3725 arraysize(kV3FrameData
));
3726 scoped_ptr
<SpdyFrame
> control_frame(
3727 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3728 multiple_frame_data
.append(string(control_frame
->data(),
3729 control_frame
->size()));
3730 visitor
.SimulateInFramer(
3731 reinterpret_cast<unsigned const char*>(multiple_frame_data
.data()),
3732 multiple_frame_data
.length());
3733 EXPECT_EQ(0, visitor
.error_count_
);
3734 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
3735 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
3738 TEST_P(SpdyFramerTest
, CreateContinuationUncompressed
) {
3739 if (spdy_version_
<= SPDY3
) {
3743 SpdyFramer
framer(spdy_version_
);
3744 framer
.set_enable_compression(false);
3745 const char kDescription
[] = "CONTINUATION frame";
3747 const unsigned char kFrameData
[] = {
3748 0x00, 0x12, 0x09, 0x00, // CONTINUATION
3749 0x00, 0x00, 0x00, 0x2a, // Stream 42
3750 0x00, 0x03, 0x62, 0x61, // @.ba
3751 0x72, 0x03, 0x66, 0x6f, // r.fo
3752 0x6f, 0x00, 0x03, 0x66, // o@.f
3753 0x6f, 0x6f, 0x03, 0x62, // oo.b
3757 SpdyContinuationIR
continuation(42);
3758 continuation
.SetHeader("bar", "foo");
3759 continuation
.SetHeader("foo", "bar");
3760 scoped_ptr
<SpdySerializedFrame
> frame(
3761 framer
.SerializeContinuation(continuation
));
3762 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3765 TEST_P(SpdyFramerTest
, ReadCompressedPushPromise
) {
3766 if (spdy_version_
<= SPDY3
) {
3770 SpdyFramer
framer(spdy_version_
);
3771 SpdyPushPromiseIR
push_promise(42, 57);
3772 push_promise
.SetHeader("foo", "bar");
3773 push_promise
.SetHeader("bar", "foofoo");
3774 SpdyHeaderBlock headers
= push_promise
.name_value_block();
3775 scoped_ptr
<SpdySerializedFrame
> frame(
3776 framer
.SerializePushPromise(push_promise
));
3777 EXPECT_TRUE(frame
.get() != NULL
);
3778 TestSpdyVisitor
visitor(spdy_version_
);
3779 visitor
.use_compression_
= true;
3780 visitor
.SimulateInFramer(
3781 reinterpret_cast<unsigned char*>(frame
->data()),
3783 EXPECT_EQ(42u, visitor
.last_push_promise_stream_
);
3784 EXPECT_EQ(57u, visitor
.last_push_promise_promised_stream_
);
3785 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3788 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuationAndPadding
) {
3789 if (spdy_version_
<= SPDY3
) {
3793 const unsigned char kInput
[] = {
3794 0x00, 0x14, 0x01, 0x08, // HEADERS: PAD_LOW
3795 0x00, 0x00, 0x00, 0x01, // Stream 1
3796 0x03, // Padding of 3.
3797 0x00, 0x06, 0x63, 0x6f,
3798 0x6f, 0x6b, 0x69, 0x65,
3799 0x07, 0x66, 0x6f, 0x6f,
3800 0x3d, 0x62, 0x61, 0x72,
3803 0x00, 0x1a, 0x09, 0x18, // CONTINUATION: PAD_LOW & PAD_HIGH
3804 0x00, 0x00, 0x00, 0x01, // Stream 1
3805 0x00, 0x04, // Padding of 4.
3806 0x00, 0x06, 0x63, 0x6f,
3807 0x6f, 0x6b, 0x69, 0x65,
3808 0x08, 0x62, 0x61, 0x7a,
3809 0x3d, 0x62, 0x69, 0x6e,
3810 0x67, 0x00, 0x06, 0x63,
3811 0x00, 0x00, 0x00, 0x00,
3813 0x00, 0x13, 0x09, 0x0c, // CONTINUATION: PAD_LOW & END_HEADERS
3814 0x00, 0x00, 0x00, 0x01, // Stream 1
3815 0x00, // Padding of 0.
3816 0x6f, 0x6f, 0x6b, 0x69,
3817 0x65, 0x00, 0x00, 0x04,
3818 0x6e, 0x61, 0x6d, 0x65,
3819 0x05, 0x76, 0x61, 0x6c,
3823 TestSpdyVisitor
visitor(spdy_version_
);
3824 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3826 EXPECT_EQ(0, visitor
.error_count_
);
3827 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3828 EXPECT_EQ(2, visitor
.continuation_count_
);
3829 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3830 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3832 EXPECT_THAT(visitor
.headers_
, ElementsAre(
3833 Pair("cookie", "foo=bar; baz=bing; "),
3834 Pair("name", "value")));
3837 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuationAndFin
) {
3838 if (spdy_version_
<= SPDY3
) {
3842 const unsigned char kInput
[] = {
3843 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
3844 0x00, 0x00, 0x00, 0x01, // Stream 1
3845 0x00, 0x06, 0x63, 0x6f,
3846 0x6f, 0x6b, 0x69, 0x65,
3847 0x07, 0x66, 0x6f, 0x6f,
3848 0x3d, 0x62, 0x61, 0x72,
3850 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3851 0x00, 0x00, 0x00, 0x01, // Stream 1
3852 0x00, 0x06, 0x63, 0x6f,
3853 0x6f, 0x6b, 0x69, 0x65,
3854 0x08, 0x62, 0x61, 0x7a,
3855 0x3d, 0x62, 0x69, 0x6e,
3856 0x67, 0x00, 0x06, 0x63,
3858 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3859 0x00, 0x00, 0x00, 0x01, // Stream 1
3860 0x6f, 0x6f, 0x6b, 0x69,
3861 0x65, 0x00, 0x00, 0x04,
3862 0x6e, 0x61, 0x6d, 0x65,
3863 0x05, 0x76, 0x61, 0x6c,
3867 SpdyFramer
framer(spdy_version_
);
3868 TestSpdyVisitor
visitor(spdy_version_
);
3869 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3871 EXPECT_EQ(0, visitor
.error_count_
);
3872 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3873 EXPECT_EQ(2, visitor
.continuation_count_
);
3874 EXPECT_EQ(1, visitor
.fin_flag_count_
);
3875 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3876 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
3878 EXPECT_THAT(visitor
.headers_
, ElementsAre(
3879 Pair("cookie", "foo=bar; baz=bing; "),
3880 Pair("name", "value")));
3883 TEST_P(SpdyFramerTest
, ReadPushPromiseWithContinuationAndPadding
) {
3884 if (spdy_version_
<= SPDY3
) {
3888 const unsigned char kInput
[] = {
3889 0x00, 0x18, 0x05, 0x18, // PUSH_PROMISE: PAD_LOW & PAD_HIGH
3890 0x00, 0x00, 0x00, 0x01, // Stream 1
3891 0x00, 0x00, 0x00, 0x2A, // Promised stream 42
3892 0x00, 0x02, // Padding of 2.
3893 0x00, 0x06, 0x63, 0x6f,
3894 0x6f, 0x6b, 0x69, 0x65,
3895 0x07, 0x66, 0x6f, 0x6f,
3896 0x3d, 0x62, 0x61, 0x72,
3899 0x00, 0x14, 0x09, 0x00, // CONTINUATION:
3900 0x00, 0x00, 0x00, 0x01, // Stream 1
3901 0x00, 0x06, 0x63, 0x6f,
3902 0x6f, 0x6b, 0x69, 0x65,
3903 0x08, 0x62, 0x61, 0x7a,
3904 0x3d, 0x62, 0x69, 0x6e,
3905 0x67, 0x00, 0x06, 0x63,
3907 0x00, 0x17, 0x09, 0x0c, // CONTINUATION: PAD_LOW & END_HEADERS
3908 0x00, 0x00, 0x00, 0x01, // Stream 1
3909 0x04, // Padding of 4.
3910 0x6f, 0x6f, 0x6b, 0x69,
3911 0x65, 0x00, 0x00, 0x04,
3912 0x6e, 0x61, 0x6d, 0x65,
3913 0x05, 0x76, 0x61, 0x6c,
3914 0x75, 0x65, 0x00, 0x00,
3918 SpdyFramer
framer(spdy_version_
);
3919 TestSpdyVisitor
visitor(spdy_version_
);
3920 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3922 EXPECT_EQ(0, visitor
.error_count_
);
3923 EXPECT_EQ(1u, visitor
.last_push_promise_stream_
);
3924 EXPECT_EQ(42u, visitor
.last_push_promise_promised_stream_
);
3925 EXPECT_EQ(2, visitor
.continuation_count_
);
3926 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3927 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3929 EXPECT_THAT(visitor
.headers_
, ElementsAre(
3930 Pair("cookie", "foo=bar; baz=bing; "),
3931 Pair("name", "value")));
3934 TEST_P(SpdyFramerTest
, ReadContinuationWithWrongStreamId
) {
3935 if (spdy_version_
<= SPDY3
) {
3939 const unsigned char kInput
[] = {
3940 0x00, 0x10, 0x01, 0x00, // HEADERS
3941 0x00, 0x00, 0x00, 0x01, // Stream 1
3942 0x00, 0x06, 0x63, 0x6f,
3943 0x6f, 0x6b, 0x69, 0x65,
3944 0x07, 0x66, 0x6f, 0x6f,
3945 0x3d, 0x62, 0x61, 0x72,
3947 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3948 0x00, 0x00, 0x00, 0x02, // Stream 2
3949 0x00, 0x06, 0x63, 0x6f,
3950 0x6f, 0x6b, 0x69, 0x65,
3951 0x08, 0x62, 0x61, 0x7a,
3952 0x3d, 0x62, 0x69, 0x6e,
3953 0x67, 0x00, 0x06, 0x63,
3956 SpdyFramer
framer(spdy_version_
);
3957 TestSpdyVisitor
visitor(spdy_version_
);
3958 framer
.set_visitor(&visitor
);
3959 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3961 EXPECT_EQ(1, visitor
.error_count_
);
3962 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
3963 visitor
.framer_
.error_code())
3964 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3965 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3966 EXPECT_EQ(0, visitor
.continuation_count_
);
3967 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3970 TEST_P(SpdyFramerTest
, ReadContinuationOutOfOrder
) {
3971 if (spdy_version_
<= SPDY3
) {
3975 const unsigned char kInput
[] = {
3976 0x00, 0x10, 0x09, 0x00, // CONTINUATION
3977 0x00, 0x00, 0x00, 0x01, // Stream 1
3978 0x00, 0x06, 0x63, 0x6f,
3979 0x6f, 0x6b, 0x69, 0x65,
3980 0x07, 0x66, 0x6f, 0x6f,
3981 0x3d, 0x62, 0x61, 0x72,
3984 SpdyFramer
framer(spdy_version_
);
3985 TestSpdyVisitor
visitor(spdy_version_
);
3986 framer
.set_visitor(&visitor
);
3987 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3989 EXPECT_EQ(1, visitor
.error_count_
);
3990 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
3991 visitor
.framer_
.error_code())
3992 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3993 EXPECT_EQ(0, visitor
.continuation_count_
);
3994 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3997 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveData
) {
3998 if (spdy_version_
<= SPDY3
) {
4002 const unsigned char kInput
[] = {
4003 0x00, 0x10, 0x01, 0x00, // HEADERS
4004 0x00, 0x00, 0x00, 0x01, // Stream 1
4005 0x00, 0x06, 0x63, 0x6f,
4006 0x6f, 0x6b, 0x69, 0x65,
4007 0x07, 0x66, 0x6f, 0x6f,
4008 0x3d, 0x62, 0x61, 0x72,
4010 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4011 0x00, 0x00, 0x00, 0x04,
4012 0xde, 0xad, 0xbe, 0xef,
4015 SpdyFramer
framer(spdy_version_
);
4016 TestSpdyVisitor
visitor(spdy_version_
);
4017 framer
.set_visitor(&visitor
);
4018 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4020 EXPECT_EQ(1, visitor
.error_count_
);
4021 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4022 visitor
.framer_
.error_code())
4023 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4024 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4025 EXPECT_EQ(0, visitor
.continuation_count_
);
4026 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4027 EXPECT_EQ(0, visitor
.data_frame_count_
);
4030 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveControlFrame
) {
4031 if (spdy_version_
<= SPDY3
) {
4035 const unsigned char kInput
[] = {
4036 0x00, 0x10, 0x01, 0x00, // HEADERS
4037 0x00, 0x00, 0x00, 0x01, // Stream 1
4038 0x00, 0x06, 0x63, 0x6f,
4039 0x6f, 0x6b, 0x69, 0x65,
4040 0x07, 0x66, 0x6f, 0x6f,
4041 0x3d, 0x62, 0x61, 0x72,
4043 0x00, 0x14, 0x08, 0x00, // HEADERS
4044 0x00, 0x00, 0x00, 0x01, // Stream 1
4045 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4046 0x6f, 0x6b, 0x69, 0x65,
4047 0x08, 0x62, 0x61, 0x7a,
4048 0x3d, 0x62, 0x69, 0x6e,
4049 0x67, 0x00, 0x06, 0x63,
4052 SpdyFramer
framer(spdy_version_
);
4053 TestSpdyVisitor
visitor(spdy_version_
);
4054 framer
.set_visitor(&visitor
);
4055 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4057 EXPECT_EQ(1, visitor
.error_count_
);
4058 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4059 visitor
.framer_
.error_code())
4060 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4061 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4062 EXPECT_EQ(0, visitor
.continuation_count_
);
4063 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4064 EXPECT_EQ(0, visitor
.data_frame_count_
);
4067 TEST_P(SpdyFramerTest
, EndSegmentOnDataFrame
) {
4068 if (spdy_version_
<= SPDY3
) {
4071 const unsigned char kInput
[] = {
4072 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4073 0x00, 0x00, 0x00, 0x01, // Stream 1
4074 0xde, 0xad, 0xbe, 0xef,
4075 0xde, 0xad, 0xbe, 0xef,
4076 0xde, 0xad, 0xbe, 0xef,
4079 TestSpdyVisitor
visitor(spdy_version_
);
4080 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4082 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4083 EXPECT_EQ(0, visitor
.error_count_
);
4084 EXPECT_EQ(12, visitor
.data_bytes_
);
4085 EXPECT_EQ(0, visitor
.fin_frame_count_
);
4086 EXPECT_EQ(0, visitor
.fin_flag_count_
);
4089 TEST_P(SpdyFramerTest
, EndSegmentOnHeadersFrame
) {
4090 if (spdy_version_
<= SPDY3
) {
4093 const unsigned char kInput
[] = {
4094 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4095 0x00, 0x00, 0x00, 0x01, // Stream 1
4096 0x00, 0x06, 0x63, 0x6f,
4097 0x6f, 0x6b, 0x69, 0x65,
4098 0x07, 0x66, 0x6f, 0x6f,
4099 0x3d, 0x62, 0x61, 0x72,
4102 TestSpdyVisitor
visitor(spdy_version_
);
4103 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4105 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4106 EXPECT_EQ(0, visitor
.error_count_
);
4107 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4108 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4110 EXPECT_THAT(visitor
.headers_
, ElementsAre(
4111 Pair("cookie", "foo=bar")));
4114 TEST_P(SpdyFramerTest
, ReadGarbage
) {
4115 SpdyFramer
framer(spdy_version_
);
4116 unsigned char garbage_frame
[256];
4117 memset(garbage_frame
, ~0, sizeof(garbage_frame
));
4118 TestSpdyVisitor
visitor(spdy_version_
);
4119 visitor
.use_compression_
= false;
4120 visitor
.SimulateInFramer(garbage_frame
, sizeof(garbage_frame
));
4121 EXPECT_EQ(1, visitor
.error_count_
);
4124 TEST_P(SpdyFramerTest
, ReadGarbageWithValidLength
) {
4128 SpdyFramer
framer(spdy_version_
);
4129 const unsigned char kFrameData
[] = {
4130 0x00, 0x10, 0xff, 0xff,
4131 0xff, 0xff, 0xff, 0xff,
4132 0xff, 0xff, 0xff, 0xff,
4133 0xff, 0xff, 0xff, 0xff,
4135 TestSpdyVisitor
visitor(spdy_version_
);
4136 visitor
.use_compression_
= false;
4137 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
4138 EXPECT_EQ(1, visitor
.error_count_
);
4141 TEST_P(SpdyFramerTest
, ReadGarbageWithValidVersion
) {
4143 // Not valid for SPDY 4 since there is no version field.
4146 SpdyFramer
framer(spdy_version_
);
4147 const unsigned char kFrameData
[] = {
4148 0x80, spdy_version_ch_
, 0xff, 0xff,
4149 0xff, 0xff, 0xff, 0xff,
4151 TestSpdyVisitor
visitor(spdy_version_
);
4152 visitor
.use_compression_
= false;
4153 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
4154 EXPECT_EQ(1, visitor
.error_count_
);
4157 TEST_P(SpdyFramerTest
, ReadGarbageHPACKEncoding
) {
4158 if (spdy_version_
<= SPDY3
) {
4161 const unsigned char kInput
[] = {
4162 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4163 0x00, 0x00, 0x00, 0x01, // Stream 1
4164 0xef, 0xef, 0xff, 0xff,
4165 0xff, 0xff, 0xff, 0xff,
4166 0xff, 0xff, 0xff, 0xff,
4167 0xff, 0xff, 0xff, 0xff,
4171 TestSpdyVisitor
visitor(spdy_version_
);
4172 visitor
.SimulateInFramer(kInput
, arraysize(kInput
));
4173 EXPECT_EQ(1, visitor
.error_count_
);
4176 TEST_P(SpdyFramerTest
, SizesTest
) {
4177 SpdyFramer
framer(spdy_version_
);
4178 EXPECT_EQ(8u, framer
.GetDataFrameMinimumSize());
4179 if (IsSpdy4() || IsSpdy5()) {
4180 EXPECT_EQ(8u, framer
.GetSynReplyMinimumSize());
4181 EXPECT_EQ(12u, framer
.GetRstStreamMinimumSize());
4182 EXPECT_EQ(8u, framer
.GetSettingsMinimumSize());
4183 EXPECT_EQ(16u, framer
.GetPingSize());
4184 EXPECT_EQ(16u, framer
.GetGoAwayMinimumSize());
4185 EXPECT_EQ(8u, framer
.GetHeadersMinimumSize());
4186 EXPECT_EQ(12u, framer
.GetWindowUpdateSize());
4187 EXPECT_EQ(8u, framer
.GetBlockedSize());
4188 EXPECT_EQ(12u, framer
.GetPushPromiseMinimumSize());
4189 EXPECT_EQ(17u, framer
.GetAltSvcMinimumSize());
4190 EXPECT_EQ(8u, framer
.GetFrameMinimumSize());
4191 EXPECT_EQ(16383u, framer
.GetFrameMaximumSize());
4192 EXPECT_EQ(16375u, framer
.GetDataFrameMaximumPayload());
4194 EXPECT_EQ(8u, framer
.GetControlFrameHeaderSize());
4195 EXPECT_EQ(18u, framer
.GetSynStreamMinimumSize());
4196 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetSynReplyMinimumSize());
4197 EXPECT_EQ(16u, framer
.GetRstStreamMinimumSize());
4198 EXPECT_EQ(12u, framer
.GetSettingsMinimumSize());
4199 EXPECT_EQ(12u, framer
.GetPingSize());
4200 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer
.GetGoAwayMinimumSize());
4201 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetHeadersMinimumSize());
4202 EXPECT_EQ(16u, framer
.GetWindowUpdateSize());
4203 EXPECT_EQ(8u, framer
.GetFrameMinimumSize());
4204 EXPECT_EQ(16777223u, framer
.GetFrameMaximumSize());
4205 EXPECT_EQ(16777215u, framer
.GetDataFrameMaximumPayload());
4209 TEST_P(SpdyFramerTest
, StateToStringTest
) {
4210 EXPECT_STREQ("ERROR",
4211 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR
));
4212 EXPECT_STREQ("AUTO_RESET",
4213 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET
));
4214 EXPECT_STREQ("RESET",
4215 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET
));
4216 EXPECT_STREQ("READING_COMMON_HEADER",
4217 SpdyFramer::StateToString(
4218 SpdyFramer::SPDY_READING_COMMON_HEADER
));
4219 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4220 SpdyFramer::StateToString(
4221 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD
));
4222 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4223 SpdyFramer::StateToString(
4224 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD
));
4225 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4226 SpdyFramer::StateToString(
4227 SpdyFramer::SPDY_FORWARD_STREAM_FRAME
));
4228 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4229 SpdyFramer::StateToString(
4230 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
));
4231 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4232 SpdyFramer::StateToString(
4233 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK
));
4234 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4235 SpdyFramer::StateToString(
4236 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD
));
4237 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4238 SpdyFramer::StateToString(
4239 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD
));
4240 EXPECT_STREQ("UNKNOWN_STATE",
4241 SpdyFramer::StateToString(
4242 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD
+ 1));
4245 TEST_P(SpdyFramerTest
, ErrorCodeToStringTest
) {
4246 EXPECT_STREQ("NO_ERROR",
4247 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR
));
4248 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4249 SpdyFramer::ErrorCodeToString(
4250 SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4251 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4252 SpdyFramer::ErrorCodeToString(
4253 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4254 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4255 SpdyFramer::ErrorCodeToString(
4256 SpdyFramer::SPDY_ZLIB_INIT_FAILURE
));
4257 EXPECT_STREQ("UNSUPPORTED_VERSION",
4258 SpdyFramer::ErrorCodeToString(
4259 SpdyFramer::SPDY_UNSUPPORTED_VERSION
));
4260 EXPECT_STREQ("DECOMPRESS_FAILURE",
4261 SpdyFramer::ErrorCodeToString(
4262 SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4263 EXPECT_STREQ("COMPRESS_FAILURE",
4264 SpdyFramer::ErrorCodeToString(
4265 SpdyFramer::SPDY_COMPRESS_FAILURE
));
4266 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4267 SpdyFramer::ErrorCodeToString(
4268 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4269 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4270 SpdyFramer::ErrorCodeToString(
4271 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
));
4272 EXPECT_STREQ("UNKNOWN_ERROR",
4273 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR
));
4276 TEST_P(SpdyFramerTest
, StatusCodeToStringTest
) {
4277 EXPECT_STREQ("INVALID",
4278 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID
));
4279 EXPECT_STREQ("PROTOCOL_ERROR",
4280 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR
));
4281 EXPECT_STREQ("INVALID_STREAM",
4282 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM
));
4283 EXPECT_STREQ("REFUSED_STREAM",
4284 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM
));
4285 EXPECT_STREQ("UNSUPPORTED_VERSION",
4286 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION
));
4287 EXPECT_STREQ("CANCEL",
4288 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL
));
4289 EXPECT_STREQ("INTERNAL_ERROR",
4290 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR
));
4291 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4292 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR
));
4293 EXPECT_STREQ("UNKNOWN_STATUS",
4294 SpdyFramer::StatusCodeToString(-1));
4297 TEST_P(SpdyFramerTest
, FrameTypeToStringTest
) {
4298 EXPECT_STREQ("DATA",
4299 SpdyFramer::FrameTypeToString(DATA
));
4300 EXPECT_STREQ("SYN_STREAM",
4301 SpdyFramer::FrameTypeToString(SYN_STREAM
));
4302 EXPECT_STREQ("SYN_REPLY",
4303 SpdyFramer::FrameTypeToString(SYN_REPLY
));
4304 EXPECT_STREQ("RST_STREAM",
4305 SpdyFramer::FrameTypeToString(RST_STREAM
));
4306 EXPECT_STREQ("SETTINGS",
4307 SpdyFramer::FrameTypeToString(SETTINGS
));
4308 EXPECT_STREQ("NOOP",
4309 SpdyFramer::FrameTypeToString(NOOP
));
4310 EXPECT_STREQ("PING",
4311 SpdyFramer::FrameTypeToString(PING
));
4312 EXPECT_STREQ("GOAWAY",
4313 SpdyFramer::FrameTypeToString(GOAWAY
));
4314 EXPECT_STREQ("HEADERS",
4315 SpdyFramer::FrameTypeToString(HEADERS
));
4316 EXPECT_STREQ("WINDOW_UPDATE",
4317 SpdyFramer::FrameTypeToString(WINDOW_UPDATE
));
4318 EXPECT_STREQ("PUSH_PROMISE",
4319 SpdyFramer::FrameTypeToString(PUSH_PROMISE
));
4320 EXPECT_STREQ("CREDENTIAL",
4321 SpdyFramer::FrameTypeToString(CREDENTIAL
));
4322 EXPECT_STREQ("CONTINUATION",
4323 SpdyFramer::FrameTypeToString(CONTINUATION
));
4326 TEST_P(SpdyFramerTest
, CatchProbableHttpResponse
) {
4328 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4332 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4333 SpdyFramer
framer(spdy_version_
);
4334 framer
.set_visitor(&visitor
);
4336 EXPECT_CALL(visitor
, OnError(_
));
4337 framer
.ProcessInput("HTTP/1.1", 8);
4338 EXPECT_TRUE(framer
.probable_http_response());
4339 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4340 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4341 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4344 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4345 SpdyFramer
framer(spdy_version_
);
4346 framer
.set_visitor(&visitor
);
4348 EXPECT_CALL(visitor
, OnError(_
));
4349 framer
.ProcessInput("HTTP/1.0", 8);
4350 EXPECT_TRUE(framer
.probable_http_response());
4351 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4352 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4353 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4357 TEST_P(SpdyFramerTest
, DataFrameFlagsV2V3
) {
4358 if (spdy_version_
> SPDY3
) {
4362 for (int flags
= 0; flags
< 256; ++flags
) {
4363 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4365 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4366 SpdyFramer
framer(spdy_version_
);
4367 framer
.set_visitor(&visitor
);
4369 SpdyDataIR
data_ir(1, StringPiece("hello", 5));
4370 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4371 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4373 if (flags
& ~DATA_FLAG_FIN
) {
4374 EXPECT_CALL(visitor
, OnError(_
));
4376 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
4377 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
4378 if (flags
& DATA_FLAG_FIN
) {
4379 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4383 framer
.ProcessInput(frame
->data(), frame
->size());
4384 if (flags
& ~DATA_FLAG_FIN
) {
4385 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4386 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
,
4387 framer
.error_code())
4388 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4390 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4391 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4392 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4397 TEST_P(SpdyFramerTest
, DataFrameFlagsV4
) {
4398 if (spdy_version_
<= SPDY3
) {
4402 uint8 valid_data_flags
= DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
|
4403 DATA_FLAG_PAD_LOW
| DATA_FLAG_PAD_HIGH
;
4405 for (int flags
= 0; flags
< 256; ++flags
) {
4406 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4408 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4409 SpdyFramer
framer(spdy_version_
);
4410 framer
.set_visitor(&visitor
);
4412 SpdyDataIR
data_ir(1, StringPiece("hello", 5));
4413 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4414 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4416 if (flags
& ~valid_data_flags
) {
4417 EXPECT_CALL(visitor
, OnError(_
));
4419 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
4420 if ((flags
& DATA_FLAG_PAD_LOW
) || (flags
& DATA_FLAG_PAD_HIGH
)) {
4421 // Expect Error since we don't set pad_high and pad_low in payload.
4422 EXPECT_CALL(visitor
, OnError(_
));
4424 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
4425 if (flags
& DATA_FLAG_FIN
) {
4426 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4431 framer
.ProcessInput(frame
->data(), frame
->size());
4432 if ((flags
& ~valid_data_flags
) || (flags
& DATA_FLAG_PAD_LOW
) ||
4433 (flags
& DATA_FLAG_PAD_HIGH
)) {
4434 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4435 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
,
4436 framer
.error_code())
4437 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4439 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4440 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4441 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4446 TEST_P(SpdyFramerTest
, SynStreamFrameFlags
) {
4447 for (int flags
= 0; flags
< 256; ++flags
) {
4448 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4450 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4451 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
4452 SpdyFramer
framer(spdy_version_
);
4453 framer
.set_visitor(&visitor
);
4454 framer
.set_debug_visitor(&debug_visitor
);
4456 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(8, SYN_STREAM
, _
, _
));
4458 SpdySynStreamIR
syn_stream(8);
4459 syn_stream
.set_associated_to_stream_id(3);
4460 syn_stream
.set_priority(1);
4461 syn_stream
.SetHeader("foo", "bar");
4462 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
4463 int set_flags
= flags
;
4465 // PRIORITY required for SYN_STREAM simulation.
4466 set_flags
|= HEADERS_FLAG_PRIORITY
;
4468 // TODO(jgraettinger): Add padding to SynStreamIR, and implement framing.
4469 set_flags
&= ~HEADERS_FLAG_PAD_LOW
;
4470 set_flags
&= ~HEADERS_FLAG_PAD_HIGH
;
4472 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
4475 flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
4476 EXPECT_CALL(visitor
, OnError(_
));
4477 } else if (IsSpdy4() &&
4478 flags
& ~(CONTROL_FLAG_FIN
|
4479 HEADERS_FLAG_PRIORITY
|
4480 HEADERS_FLAG_END_HEADERS
|
4481 HEADERS_FLAG_END_SEGMENT
|
4482 HEADERS_FLAG_PAD_LOW
|
4483 HEADERS_FLAG_PAD_HIGH
)) {
4484 EXPECT_CALL(visitor
, OnError(_
));
4486 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(8, SYN_STREAM
, _
));
4488 EXPECT_CALL(visitor
, OnSynStream(8, 0, 1, flags
& CONTROL_FLAG_FIN
,
4491 EXPECT_CALL(visitor
, OnSynStream(8, 3, 1, flags
& CONTROL_FLAG_FIN
,
4492 flags
& CONTROL_FLAG_UNIDIRECTIONAL
));
4494 EXPECT_CALL(visitor
, OnControlFrameHeaderData(8, _
, _
))
4495 .WillRepeatedly(testing::Return(true));
4496 if (flags
& DATA_FLAG_FIN
&& (!IsSpdy4() ||
4497 flags
& HEADERS_FLAG_END_HEADERS
)) {
4498 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4500 // Do not close the stream if we are expecting a CONTINUATION frame.
4501 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
4505 framer
.ProcessInput(frame
->data(), frame
->size());
4507 flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
4508 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4509 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4510 framer
.error_code())
4511 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4512 } else if (IsSpdy4() &&
4513 flags
& ~(CONTROL_FLAG_FIN
|
4514 HEADERS_FLAG_PRIORITY
|
4515 HEADERS_FLAG_END_HEADERS
|
4516 HEADERS_FLAG_END_SEGMENT
|
4517 HEADERS_FLAG_PAD_LOW
|
4518 HEADERS_FLAG_PAD_HIGH
)) {
4519 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4520 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4521 framer
.error_code())
4522 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4524 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4525 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4526 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4531 TEST_P(SpdyFramerTest
, SynReplyFrameFlags
) {
4533 // Covered by HEADERS case.
4536 for (int flags
= 0; flags
< 256; ++flags
) {
4537 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4539 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4540 SpdyFramer
framer(spdy_version_
);
4541 framer
.set_visitor(&visitor
);
4543 SpdySynReplyIR
syn_reply(37);
4544 syn_reply
.SetHeader("foo", "bar");
4545 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
4546 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4548 if (flags
& ~CONTROL_FLAG_FIN
) {
4549 EXPECT_CALL(visitor
, OnError(_
));
4551 EXPECT_CALL(visitor
, OnSynReply(37, flags
& CONTROL_FLAG_FIN
));
4552 EXPECT_CALL(visitor
, OnControlFrameHeaderData(37, _
, _
))
4553 .WillRepeatedly(testing::Return(true));
4554 if (flags
& DATA_FLAG_FIN
) {
4555 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4559 framer
.ProcessInput(frame
->data(), frame
->size());
4560 if (flags
& ~CONTROL_FLAG_FIN
) {
4561 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4562 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4563 framer
.error_code())
4564 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4566 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4567 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4568 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4573 TEST_P(SpdyFramerTest
, RstStreamFrameFlags
) {
4574 for (int flags
= 0; flags
< 256; ++flags
) {
4575 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4577 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4578 SpdyFramer
framer(spdy_version_
);
4579 framer
.set_visitor(&visitor
);
4581 SpdyRstStreamIR
rst_stream(13, RST_STREAM_CANCEL
, "");
4582 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
4583 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4586 EXPECT_CALL(visitor
, OnError(_
));
4588 EXPECT_CALL(visitor
, OnRstStream(13, RST_STREAM_CANCEL
));
4591 framer
.ProcessInput(frame
->data(), frame
->size());
4593 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4594 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4595 framer
.error_code())
4596 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4598 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4599 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4600 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4605 TEST_P(SpdyFramerTest
, SettingsFrameFlagsOldFormat
) {
4606 if (spdy_version_
> SPDY3
) { return; }
4607 for (int flags
= 0; flags
< 256; ++flags
) {
4608 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4610 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4611 SpdyFramer
framer(spdy_version_
);
4612 framer
.set_visitor(&visitor
);
4614 SpdySettingsIR settings_ir
;
4615 settings_ir
.AddSetting(SETTINGS_UPLOAD_BANDWIDTH
,
4619 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
4620 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4622 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
4623 EXPECT_CALL(visitor
, OnError(_
));
4625 EXPECT_CALL(visitor
, OnSettings(
4626 flags
& SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
));
4627 EXPECT_CALL(visitor
, OnSetting(SETTINGS_UPLOAD_BANDWIDTH
,
4628 SETTINGS_FLAG_NONE
, 54321));
4629 EXPECT_CALL(visitor
, OnSettingsEnd());
4632 framer
.ProcessInput(frame
->data(), frame
->size());
4633 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
4634 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4635 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4636 framer
.error_code())
4637 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4639 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4640 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4641 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4646 TEST_P(SpdyFramerTest
, SettingsFrameFlags
) {
4647 if (spdy_version_
<= SPDY3
) { return; }
4648 for (int flags
= 0; flags
< 256; ++flags
) {
4649 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4651 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4652 SpdyFramer
framer(spdy_version_
);
4653 framer
.set_visitor(&visitor
);
4655 SpdySettingsIR settings_ir
;
4656 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 0, 16);
4657 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
4658 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4661 EXPECT_CALL(visitor
, OnError(_
));
4663 EXPECT_CALL(visitor
, OnSettings(flags
& SETTINGS_FLAG_ACK
));
4664 EXPECT_CALL(visitor
, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 16));
4665 EXPECT_CALL(visitor
, OnSettingsEnd());
4668 framer
.ProcessInput(frame
->data(), frame
->size());
4669 if (flags
& ~SETTINGS_FLAG_ACK
) {
4670 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4671 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4672 framer
.error_code())
4673 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4674 } else if (flags
& SETTINGS_FLAG_ACK
) {
4675 // The frame is invalid because ACK frames should have no payload.
4676 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4677 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
4678 framer
.error_code())
4679 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4681 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4682 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4683 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4688 TEST_P(SpdyFramerTest
, GoawayFrameFlags
) {
4689 for (int flags
= 0; flags
< 256; ++flags
) {
4690 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4692 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4693 SpdyFramer
framer(spdy_version_
);
4694 framer
.set_visitor(&visitor
);
4696 SpdyGoAwayIR
goaway_ir(97, GOAWAY_OK
, "test");
4697 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
4698 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4701 EXPECT_CALL(visitor
, OnError(_
));
4703 EXPECT_CALL(visitor
, OnGoAway(97, GOAWAY_OK
));
4706 framer
.ProcessInput(frame
->data(), frame
->size());
4708 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4709 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4710 framer
.error_code())
4711 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4713 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4714 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4715 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4720 TEST_P(SpdyFramerTest
, HeadersFrameFlags
) {
4721 for (int flags
= 0; flags
< 256; ++flags
) {
4722 if (IsSpdy4() && flags
& HEADERS_FLAG_PRIORITY
) {
4723 // Covered by SYN_STREAM case.
4726 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4728 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4729 SpdyFramer
framer(spdy_version_
);
4730 framer
.set_visitor(&visitor
);
4732 SpdyHeadersIR
headers_ir(57);
4733 headers_ir
.SetHeader("foo", "bar");
4734 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
4735 int set_flags
= flags
;
4737 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
4738 // and implement framing.
4739 set_flags
&= ~HEADERS_FLAG_PAD_LOW
;
4740 set_flags
&= ~HEADERS_FLAG_PAD_HIGH
;
4742 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
4744 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
4745 EXPECT_CALL(visitor
, OnError(_
));
4746 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
4747 HEADERS_FLAG_END_HEADERS
|
4748 HEADERS_FLAG_END_SEGMENT
|
4749 HEADERS_FLAG_PAD_LOW
|
4750 HEADERS_FLAG_PAD_HIGH
)) {
4751 EXPECT_CALL(visitor
, OnError(_
));
4753 EXPECT_CALL(visitor
, OnHeaders(57,
4754 flags
& CONTROL_FLAG_FIN
,
4755 (flags
& HEADERS_FLAG_END_HEADERS
) ||
4757 EXPECT_CALL(visitor
, OnControlFrameHeaderData(57, _
, _
))
4758 .WillRepeatedly(testing::Return(true));
4759 if (flags
& DATA_FLAG_FIN
&& (!IsSpdy4() ||
4760 flags
& HEADERS_FLAG_END_HEADERS
)) {
4761 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4763 // Do not close the stream if we are expecting a CONTINUATION frame.
4764 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
4768 framer
.ProcessInput(frame
->data(), frame
->size());
4769 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
4770 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4771 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4772 framer
.error_code())
4773 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4774 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
4775 HEADERS_FLAG_END_HEADERS
|
4776 HEADERS_FLAG_END_SEGMENT
|
4777 HEADERS_FLAG_PAD_LOW
|
4778 HEADERS_FLAG_PAD_HIGH
)) {
4779 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4780 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4781 framer
.error_code())
4782 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4783 } else if (IsSpdy4() && ~(flags
& HEADERS_FLAG_END_HEADERS
)) {
4784 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4785 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4786 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4788 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4789 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4790 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4795 TEST_P(SpdyFramerTest
, PingFrameFlags
) {
4796 for (int flags
= 0; flags
< 256; ++flags
) {
4797 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4799 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4800 SpdyFramer
framer(spdy_version_
);
4801 framer
.set_visitor(&visitor
);
4803 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePing(SpdyPingIR(42)));
4804 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4806 if (spdy_version_
> SPDY3
&&
4807 flags
== PING_FLAG_ACK
) {
4808 EXPECT_CALL(visitor
, OnPing(42, true));
4809 } else if (flags
== 0) {
4810 EXPECT_CALL(visitor
, OnPing(42, false));
4812 EXPECT_CALL(visitor
, OnError(_
));
4815 framer
.ProcessInput(frame
->data(), frame
->size());
4816 if ((spdy_version_
> SPDY3
&& flags
== PING_FLAG_ACK
) ||
4818 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4819 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4820 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4822 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4823 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4824 framer
.error_code())
4825 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4830 TEST_P(SpdyFramerTest
, WindowUpdateFrameFlags
) {
4831 for (int flags
= 0; flags
< 256; ++flags
) {
4832 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4834 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4835 SpdyFramer
framer(spdy_version_
);
4836 framer
.set_visitor(&visitor
);
4838 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
4839 SpdyWindowUpdateIR(4, 1024)));
4840 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4843 EXPECT_CALL(visitor
, OnError(_
));
4845 EXPECT_CALL(visitor
, OnWindowUpdate(4, 1024));
4848 framer
.ProcessInput(frame
->data(), frame
->size());
4850 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4851 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4852 framer
.error_code())
4853 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4855 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4856 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4857 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4862 TEST_P(SpdyFramerTest
, PushPromiseFrameFlags
) {
4863 if (spdy_version_
<= SPDY3
) {
4867 for (int flags
= 0; flags
< 256; ++flags
) {
4868 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4870 testing::StrictMock
<net::test::MockSpdyFramerVisitor
> visitor
;
4871 testing::StrictMock
<net::test::MockDebugVisitor
> debug_visitor
;
4872 SpdyFramer
framer(spdy_version_
);
4873 framer
.set_visitor(&visitor
);
4874 framer
.set_debug_visitor(&debug_visitor
);
4876 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, PUSH_PROMISE
, _
, _
));
4878 SpdyPushPromiseIR
push_promise(42, 57);
4879 push_promise
.SetHeader("foo", "bar");
4880 scoped_ptr
<SpdySerializedFrame
> frame(
4881 framer
.SerializePushPromise(push_promise
));
4882 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
4883 // and implement framing.
4884 int set_flags
= flags
& ~HEADERS_FLAG_PAD_LOW
& ~HEADERS_FLAG_PAD_HIGH
;
4885 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
4887 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
4888 HEADERS_FLAG_PAD_LOW
|
4889 HEADERS_FLAG_PAD_HIGH
)) {
4890 EXPECT_CALL(visitor
, OnError(_
));
4892 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, PUSH_PROMISE
, _
));
4893 EXPECT_CALL(visitor
, OnPushPromise(42, 57,
4894 flags
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
));
4895 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
4896 .WillRepeatedly(testing::Return(true));
4899 framer
.ProcessInput(frame
->data(), frame
->size());
4900 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
4901 HEADERS_FLAG_PAD_LOW
|
4902 HEADERS_FLAG_PAD_HIGH
)) {
4903 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4904 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4905 framer
.error_code())
4906 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4908 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4909 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4910 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4915 TEST_P(SpdyFramerTest
, ContinuationFrameFlags
) {
4916 if (spdy_version_
<= SPDY3
) {
4920 for (int flags
= 0; flags
< 256; ++flags
) {
4921 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4923 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4924 testing::StrictMock
<net::test::MockDebugVisitor
> debug_visitor
;
4925 SpdyFramer
framer(spdy_version_
);
4926 framer
.set_visitor(&visitor
);
4927 framer
.set_debug_visitor(&debug_visitor
);
4929 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, HEADERS
, _
, _
));
4930 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, HEADERS
, _
));
4931 EXPECT_CALL(visitor
, OnHeaders(42, 0, false));
4932 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
4933 .WillRepeatedly(testing::Return(true));
4934 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, CONTINUATION
, _
, _
));
4936 SpdyHeadersIR
headers_ir(42);
4937 headers_ir
.SetHeader("foo", "bar");
4938 scoped_ptr
<SpdyFrame
> frame0(framer
.SerializeHeaders(headers_ir
));
4939 SetFrameFlags(frame0
.get(), 0, spdy_version_
);
4941 SpdyContinuationIR
continuation(42);
4942 continuation
.SetHeader("foo", "bar");
4943 scoped_ptr
<SpdySerializedFrame
> frame(
4944 framer
.SerializeContinuation(continuation
));
4945 // TODO(jgraettinger): Add padding to the eventual continuation
4946 // serialization implementation.
4947 int set_flags
= flags
& ~HEADERS_FLAG_PAD_LOW
& ~HEADERS_FLAG_PAD_HIGH
;
4948 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
4950 if (flags
& ~(HEADERS_FLAG_END_HEADERS
|
4951 HEADERS_FLAG_PAD_LOW
|
4952 HEADERS_FLAG_PAD_HIGH
)) {
4953 EXPECT_CALL(visitor
, OnError(_
));
4955 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, CONTINUATION
, _
));
4956 EXPECT_CALL(visitor
, OnContinuation(42,
4957 flags
& HEADERS_FLAG_END_HEADERS
));
4958 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
4959 .WillRepeatedly(testing::Return(true));
4962 framer
.ProcessInput(frame0
->data(), frame0
->size());
4963 framer
.ProcessInput(frame
->data(), frame
->size());
4964 if (flags
& ~(HEADERS_FLAG_END_HEADERS
|
4965 HEADERS_FLAG_PAD_LOW
|
4966 HEADERS_FLAG_PAD_HIGH
)) {
4967 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4968 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4969 framer
.error_code())
4970 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4972 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4973 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4974 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4979 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
4981 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
4983 TEST_P(SpdyFramerTest
, EmptySynStream
) {
4984 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4985 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
4986 SpdyFramer
framer(spdy_version_
);
4987 framer
.set_visitor(&visitor
);
4988 framer
.set_debug_visitor(&debug_visitor
);
4990 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(1, SYN_STREAM
, _
, _
));
4992 SpdySynStreamIR
syn_stream(1);
4993 syn_stream
.set_priority(1);
4994 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
4995 // Adjust size to remove the name/value block.
4998 framer
.GetSynStreamMinimumSize() - framer
.GetControlFrameHeaderSize(),
5001 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(1, SYN_STREAM
, _
));
5002 EXPECT_CALL(visitor
, OnSynStream(1, 0, 1, false, false));
5003 EXPECT_CALL(visitor
, OnControlFrameHeaderData(1, NULL
, 0));
5005 framer
.ProcessInput(frame
->data(), framer
.GetSynStreamMinimumSize());
5006 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5007 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5008 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5011 TEST_P(SpdyFramerTest
, SettingsFlagsAndId
) {
5012 const uint32 kId
= 0x020304;
5013 const uint32 kFlags
= 0x01;
5014 const uint32 kWireFormat
= htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5016 SettingsFlagsAndId id_and_flags
=
5017 SettingsFlagsAndId::FromWireFormat(spdy_version_
, kWireFormat
);
5018 EXPECT_EQ(kId
, id_and_flags
.id());
5019 EXPECT_EQ(kFlags
, id_and_flags
.flags());
5020 EXPECT_EQ(kWireFormat
, id_and_flags
.GetWireFormat(spdy_version_
));
5023 // Test handling of a RST_STREAM with out-of-bounds status codes.
5024 TEST_P(SpdyFramerTest
, RstStreamStatusBounds
) {
5025 const unsigned char kRstStreamStatusTooLow
= 0x00;
5026 const unsigned char kRstStreamStatusTooHigh
= 0xff;
5027 const unsigned char kV3RstStreamInvalid
[] = {
5028 0x80, spdy_version_ch_
, 0x00, 0x03,
5029 0x00, 0x00, 0x00, 0x08,
5030 0x00, 0x00, 0x00, 0x01,
5031 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5033 const unsigned char kV4RstStreamInvalid
[] = {
5034 0x00, 0x04, 0x03, 0x00,
5035 0x00, 0x00, 0x00, 0x01,
5036 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5039 const unsigned char kV3RstStreamNumStatusCodes
[] = {
5040 0x80, spdy_version_ch_
, 0x00, 0x03,
5041 0x00, 0x00, 0x00, 0x08,
5042 0x00, 0x00, 0x00, 0x01,
5043 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5045 const unsigned char kV4RstStreamNumStatusCodes
[] = {
5046 0x00, 0x04, 0x03, 0x00,
5047 0x00, 0x00, 0x00, 0x01,
5048 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5051 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5052 SpdyFramer
framer(spdy_version_
);
5053 framer
.set_visitor(&visitor
);
5056 EXPECT_CALL(visitor
, OnError(_
));
5057 framer
.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid
),
5058 arraysize(kV4RstStreamInvalid
));
5059 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5060 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
5061 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5063 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
5064 framer
.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid
),
5065 arraysize(kV3RstStreamInvalid
));
5066 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5067 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5068 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5075 EXPECT_CALL(visitor
, OnError(_
));
5076 framer
.ProcessInput(
5077 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes
),
5078 arraysize(kV4RstStreamNumStatusCodes
));
5079 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5080 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
5081 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5083 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
5084 framer
.ProcessInput(
5085 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes
),
5086 arraysize(kV3RstStreamNumStatusCodes
));
5087 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5088 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5089 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5093 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5094 TEST_P(SpdyFramerTest
, GoAwayStreamIdBounds
) {
5095 const unsigned char kV2FrameData
[] = {
5096 0x80, spdy_version_ch_
, 0x00, 0x07,
5097 0x00, 0x00, 0x00, 0x04,
5098 0xff, 0xff, 0xff, 0xff,
5100 const unsigned char kV3FrameData
[] = {
5101 0x80, spdy_version_ch_
, 0x00, 0x07,
5102 0x00, 0x00, 0x00, 0x08,
5103 0xff, 0xff, 0xff, 0xff,
5104 0x00, 0x00, 0x00, 0x00,
5106 const unsigned char kV4FrameData
[] = {
5107 0x00, 0x08, 0x07, 0x00,
5108 0x00, 0x00, 0x00, 0x00,
5109 0xff, 0xff, 0xff, 0xff,
5110 0x00, 0x00, 0x00, 0x00,
5113 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5114 SpdyFramer
framer(spdy_version_
);
5115 framer
.set_visitor(&visitor
);
5117 EXPECT_CALL(visitor
, OnGoAway(0x7fffffff, GOAWAY_OK
));
5119 framer
.ProcessInput(reinterpret_cast<const char*>(kV2FrameData
),
5120 arraysize(kV2FrameData
));
5121 } else if (IsSpdy3()) {
5122 framer
.ProcessInput(reinterpret_cast<const char*>(kV3FrameData
),
5123 arraysize(kV3FrameData
));
5125 framer
.ProcessInput(reinterpret_cast<const char*>(kV4FrameData
),
5126 arraysize(kV4FrameData
));
5128 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5129 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5130 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5133 TEST_P(SpdyFramerTest
, OnBlocked
) {
5134 if (spdy_version_
<= SPDY3
) {
5138 const SpdyStreamId kStreamId
= 0;
5140 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5141 SpdyFramer
framer(spdy_version_
);
5142 framer
.set_visitor(&visitor
);
5144 EXPECT_CALL(visitor
, OnBlocked(kStreamId
));
5146 SpdyBlockedIR
blocked_ir(0);
5147 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
5148 framer
.ProcessInput(frame
->data(), framer
.GetBlockedSize());
5150 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5151 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5152 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5155 TEST_P(SpdyFramerTest
, OnAltSvc
) {
5156 if (spdy_version_
<= SPDY3
) {
5160 const SpdyStreamId kStreamId
= 1;
5162 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5163 SpdyFramer
framer(spdy_version_
);
5164 framer
.set_visitor(&visitor
);
5166 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
,
5171 StringPiece("o1")));
5173 SpdyAltSvcIR
altsvc_ir(1);
5174 altsvc_ir
.set_max_age(10);
5175 altsvc_ir
.set_port(443);
5176 altsvc_ir
.set_protocol_id("pid");
5177 altsvc_ir
.set_host("h1");
5178 altsvc_ir
.set_origin("o1");
5179 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5180 framer
.ProcessInput(frame
->data(), framer
.GetAltSvcMinimumSize() +
5181 altsvc_ir
.protocol_id().length() +
5182 altsvc_ir
.host().length() +
5183 altsvc_ir
.origin().length());
5185 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5186 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5187 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5190 TEST_P(SpdyFramerTest
, OnAltSvcNoOrigin
) {
5191 if (spdy_version_
<= SPDY3
) {
5195 const SpdyStreamId kStreamId
= 1;
5197 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5198 SpdyFramer
framer(spdy_version_
);
5199 framer
.set_visitor(&visitor
);
5201 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
,
5208 SpdyAltSvcIR
altsvc_ir(1);
5209 altsvc_ir
.set_max_age(10);
5210 altsvc_ir
.set_port(443);
5211 altsvc_ir
.set_protocol_id("pid");
5212 altsvc_ir
.set_host("h1");
5213 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5214 framer
.ProcessInput(frame
->data(), framer
.GetAltSvcMinimumSize() +
5215 altsvc_ir
.protocol_id().length() +
5216 altsvc_ir
.host().length());
5218 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5219 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5220 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5223 TEST_P(SpdyFramerTest
, OnAltSvcBadLengths
) {
5224 if (spdy_version_
<= SPDY3
) {
5228 const unsigned char kType
= static_cast<unsigned char>(
5229 SpdyConstants::SerializeFrameType(spdy_version_
, ALTSVC
));
5231 TestSpdyVisitor
visitor(spdy_version_
);
5232 SpdyFramer
framer(spdy_version_
);
5233 framer
.set_visitor(&visitor
);
5235 const unsigned char kFrameDataLargePIDLen
[] = {
5236 0x00, 0x17, kType
, 0x00,
5237 0x00, 0x00, 0x00, 0x03,
5238 0x00, 0x00, 0x00, 0x05,
5239 0x01, 0xbb, 0x00, 0x05, // Port = 443
5240 'p', 'i', 'd', '1', // Protocol-ID
5241 0x04, 'h', 'o', 's',
5246 visitor
.SimulateInFramer(kFrameDataLargePIDLen
,
5247 sizeof(kFrameDataLargePIDLen
));
5248 EXPECT_EQ(1, visitor
.error_count_
);
5249 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5250 visitor
.framer_
.error_code());
5254 TestSpdyVisitor
visitor(spdy_version_
);
5255 SpdyFramer
framer(spdy_version_
);
5256 framer
.set_visitor(&visitor
);
5257 const unsigned char kFrameDataPIDLenLargerThanFrame
[] = {
5258 0x00, 0x17, kType
, 0x00,
5259 0x00, 0x00, 0x00, 0x03,
5260 0x00, 0x00, 0x00, 0x05,
5261 0x01, 0xbb, 0x00, 0x99, // Port = 443
5262 'p', 'i', 'd', '1', // Protocol-ID
5263 0x04, 'h', 'o', 's',
5268 visitor
.SimulateInFramer(kFrameDataPIDLenLargerThanFrame
,
5269 sizeof(kFrameDataPIDLenLargerThanFrame
));
5270 EXPECT_EQ(1, visitor
.error_count_
);
5271 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5272 visitor
.framer_
.error_code());
5276 TestSpdyVisitor
visitor(spdy_version_
);
5277 SpdyFramer
framer(spdy_version_
);
5278 framer
.set_visitor(&visitor
);
5280 const unsigned char kFrameDataLargeHostLen
[] = {
5281 0x00, 0x17, kType
, 0x00,
5282 0x00, 0x00, 0x00, 0x03,
5283 0x00, 0x00, 0x00, 0x05,
5284 0x01, 0xbb, 0x00, 0x04, // Port = 443
5285 'p', 'i', 'd', '1', // Protocol-ID
5286 0x0f, 'h', 'o', 's',
5291 visitor
.SimulateInFramer(kFrameDataLargeHostLen
,
5292 sizeof(kFrameDataLargeHostLen
));
5293 EXPECT_EQ(1, visitor
.error_count_
);
5294 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5295 visitor
.framer_
.error_code());
5299 TestSpdyVisitor
visitor(spdy_version_
);
5300 SpdyFramer
framer(spdy_version_
);
5301 framer
.set_visitor(&visitor
);
5302 const unsigned char kFrameDataSmallPIDLen
[] = {
5303 0x00, 0x17, kType
, 0x00,
5304 0x00, 0x00, 0x00, 0x03,
5305 0x00, 0x00, 0x00, 0x05,
5306 0x01, 0xbb, 0x00, 0x01, // Port = 443
5307 'p', 'i', 'd', '1', // Protocol-ID
5308 0x04, 'h', 'o', 's',
5313 visitor
.SimulateInFramer(kFrameDataSmallPIDLen
,
5314 sizeof(kFrameDataSmallPIDLen
));
5315 EXPECT_EQ(1, visitor
.error_count_
);
5316 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5317 visitor
.framer_
.error_code());
5321 // Tests handling of ALTSVC frames delivered in small chunks.
5322 TEST_P(SpdyFramerTest
, ReadChunkedAltSvcFrame
) {
5323 if (spdy_version_
<= SPDY3
) {
5326 SpdyFramer
framer(spdy_version_
);
5327 SpdyAltSvcIR
altsvc_ir(1);
5328 altsvc_ir
.set_max_age(20);
5329 altsvc_ir
.set_port(443);
5330 altsvc_ir
.set_protocol_id("protocolid");
5331 altsvc_ir
.set_host("hostname");
5333 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeAltSvc(altsvc_ir
));
5334 TestSpdyVisitor
visitor(spdy_version_
);
5335 visitor
.use_compression_
= false;
5337 // Read data in small chunks.
5338 size_t framed_data
= 0;
5339 size_t unframed_data
= control_frame
->size();
5340 size_t kReadChunkSize
= 5; // Read five bytes at a time.
5341 while (unframed_data
> 0) {
5342 size_t to_read
= min(kReadChunkSize
, unframed_data
);
5343 visitor
.SimulateInFramer(
5344 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
5346 unframed_data
-= to_read
;
5347 framed_data
+= to_read
;
5349 EXPECT_EQ(0, visitor
.error_count_
);
5350 EXPECT_EQ(1, visitor
.altsvc_count_
);
5351 EXPECT_EQ(20u, visitor
.test_altsvc_ir_
.max_age());
5352 EXPECT_EQ(443u, visitor
.test_altsvc_ir_
.port());
5353 EXPECT_EQ("protocolid", visitor
.test_altsvc_ir_
.protocol_id());
5354 EXPECT_EQ("hostname", visitor
.test_altsvc_ir_
.host());
5357 // Tests handling of PRIORITY frames.
5358 TEST_P(SpdyFramerTest
, ReadPriority
) {
5359 if (spdy_version_
<= SPDY3
) {
5363 const unsigned char kFrameData
[] = {
5364 0x00, 0x05, 0x02, 0x00, // PRIORITY frame
5365 0x00, 0x00, 0x00, 0x03, // stream ID 3
5366 0x00, 0x00, 0x00, 0x01, // dependent on stream id 1
5370 TestSpdyVisitor
visitor(spdy_version_
);
5371 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
5373 EXPECT_EQ(SpdyFramer::SPDY_RESET
, visitor
.framer_
.state());
5374 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, visitor
.framer_
.error_code())
5375 << SpdyFramer::ErrorCodeToString(visitor
.framer_
.error_code());
5378 // Tests handling of PRIORITY frame with incorrect size.
5379 TEST_P(SpdyFramerTest
, ReadIncorrectlySizedPriority
) {
5380 if (spdy_version_
<= SPDY3
) {
5384 // PRIORITY frame of size 4, which isn't correct.
5385 const unsigned char kFrameData
[] = {
5386 0x00, 0x04, 0x02, 0x00,
5387 0x00, 0x00, 0x00, 0x03,
5388 0x00, 0x00, 0x00, 0x01,
5391 TestSpdyVisitor
visitor(spdy_version_
);
5392 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
5394 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, visitor
.framer_
.state());
5395 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5396 visitor
.framer_
.error_code())
5397 << SpdyFramer::ErrorCodeToString(visitor
.framer_
.error_code());
5400 TEST_P(SpdyFramerTest
, PriorityWeightMapping
) {
5401 if (spdy_version_
<= SPDY3
) {
5404 SpdyFramer
framer(spdy_version_
);
5406 EXPECT_EQ(255u, framer
.MapPriorityToWeight(0));
5407 EXPECT_EQ(219u, framer
.MapPriorityToWeight(1));
5408 EXPECT_EQ(182u, framer
.MapPriorityToWeight(2));
5409 EXPECT_EQ(146u, framer
.MapPriorityToWeight(3));
5410 EXPECT_EQ(109u, framer
.MapPriorityToWeight(4));
5411 EXPECT_EQ(73u, framer
.MapPriorityToWeight(5));
5412 EXPECT_EQ(36u, framer
.MapPriorityToWeight(6));
5413 EXPECT_EQ(0u, framer
.MapPriorityToWeight(7));
5415 EXPECT_EQ(0u, framer
.MapWeightToPriority(255));
5416 EXPECT_EQ(0u, framer
.MapWeightToPriority(220));
5417 EXPECT_EQ(1u, framer
.MapWeightToPriority(219));
5418 EXPECT_EQ(1u, framer
.MapWeightToPriority(183));
5419 EXPECT_EQ(2u, framer
.MapWeightToPriority(182));
5420 EXPECT_EQ(2u, framer
.MapWeightToPriority(147));
5421 EXPECT_EQ(3u, framer
.MapWeightToPriority(146));
5422 EXPECT_EQ(3u, framer
.MapWeightToPriority(110));
5423 EXPECT_EQ(4u, framer
.MapWeightToPriority(109));
5424 EXPECT_EQ(4u, framer
.MapWeightToPriority(74));
5425 EXPECT_EQ(5u, framer
.MapWeightToPriority(73));
5426 EXPECT_EQ(5u, framer
.MapWeightToPriority(37));
5427 EXPECT_EQ(6u, framer
.MapWeightToPriority(36));
5428 EXPECT_EQ(6u, framer
.MapWeightToPriority(1));
5429 EXPECT_EQ(7u, framer
.MapWeightToPriority(0));