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_framer.h"
15 #include "net/spdy/spdy_protocol.h"
16 #include "net/spdy/spdy_test_utils.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/platform_test.h"
20 using base::StringPiece
;
24 using std::numeric_limits
;
25 using testing::ElementsAre
;
33 static const size_t kMaxDecompressedSize
= 1024;
35 class MockDebugVisitor
: public SpdyFramerDebugVisitorInterface
{
37 MOCK_METHOD4(OnSendCompressedFrame
, void(SpdyStreamId stream_id
,
42 MOCK_METHOD3(OnReceiveCompressedFrame
, void(SpdyStreamId stream_id
,
47 class SpdyFramerTestUtil
{
49 // Decompress a single frame using the decompression context held by
50 // the SpdyFramer. The implemention is meant for use only in tests
51 // and will CHECK fail if the input is anything other than a single,
52 // well-formed compressed frame.
54 // Returns a new decompressed SpdyFrame.
55 template<class SpdyFrameType
> static SpdyFrame
* DecompressFrame(
56 SpdyFramer
* framer
, const SpdyFrameType
& frame
) {
57 DecompressionVisitor
visitor(framer
->protocol_version());
58 framer
->set_visitor(&visitor
);
59 CHECK_EQ(frame
.size(), framer
->ProcessInput(frame
.data(), frame
.size()));
60 CHECK_EQ(SpdyFramer::SPDY_RESET
, framer
->state());
61 framer
->set_visitor(NULL
);
63 char* buffer
= visitor
.ReleaseBuffer();
64 CHECK(buffer
!= NULL
);
65 SpdyFrame
* decompressed_frame
= new SpdyFrame(buffer
, visitor
.size(), true);
66 if (framer
->protocol_version() == 4) {
67 SetFrameLength(decompressed_frame
,
69 framer
->protocol_version());
71 SetFrameLength(decompressed_frame
,
72 visitor
.size() - framer
->GetControlFrameHeaderSize(),
73 framer
->protocol_version());
75 return decompressed_frame
;
78 class DecompressionVisitor
: public SpdyFramerVisitorInterface
{
80 explicit DecompressionVisitor(SpdyMajorVersion version
)
81 : version_(version
), size_(0), finished_(false) {}
84 CHECK(buffer_
.get() == NULL
);
87 buffer_
.reset(new char[kMaxDecompressedSize
]);
90 virtual void OnError(SpdyFramer
* framer
) OVERRIDE
{ LOG(FATAL
); }
91 virtual void OnDataFrameHeader(SpdyStreamId stream_id
,
94 LOG(FATAL
) << "Unexpected data frame header";
96 virtual void OnStreamFrameData(SpdyStreamId stream_id
,
103 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
104 const char* header_data
,
105 size_t len
) OVERRIDE
{
106 CHECK(buffer_
.get() != NULL
);
107 CHECK_GE(kMaxDecompressedSize
, size_
+ len
);
110 memcpy(buffer_
.get() + size_
, header_data
, len
);
119 virtual void OnSynStream(SpdyStreamId stream_id
,
120 SpdyStreamId associated_stream_id
,
121 SpdyPriority priority
,
123 bool unidirectional
) OVERRIDE
{
124 SpdyFramer
framer(version_
);
125 framer
.set_enable_compression(false);
126 SpdySynStreamIR
syn_stream(stream_id
);
127 syn_stream
.set_associated_to_stream_id(associated_stream_id
);
128 syn_stream
.set_priority(priority
);
129 syn_stream
.set_fin(fin
);
130 syn_stream
.set_unidirectional(unidirectional
);
131 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
133 memcpy(buffer_
.get(), frame
->data(), framer
.GetSynStreamMinimumSize());
134 size_
+= framer
.GetSynStreamMinimumSize();
137 virtual void OnSynReply(SpdyStreamId stream_id
, bool fin
) OVERRIDE
{
138 SpdyFramer
framer(version_
);
139 framer
.set_enable_compression(false);
140 SpdyHeadersIR
headers(stream_id
);
141 headers
.set_fin(fin
);
142 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
144 memcpy(buffer_
.get(), frame
->data(), framer
.GetHeadersMinimumSize());
145 size_
+= framer
.GetSynStreamMinimumSize();
148 virtual void OnRstStream(SpdyStreamId stream_id
,
149 SpdyRstStreamStatus status
) OVERRIDE
{
152 virtual void OnSetting(SpdySettingsIds id
,
154 uint32 value
) OVERRIDE
{
157 virtual void OnPing(SpdyPingId unique_id
, bool is_ack
) OVERRIDE
{
160 virtual void OnSettingsEnd() OVERRIDE
{ LOG(FATAL
); }
161 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id
,
162 SpdyGoAwayStatus status
) OVERRIDE
{
166 virtual void OnHeaders(SpdyStreamId stream_id
,
169 SpdyFramer
framer(version_
);
170 framer
.set_enable_compression(false);
171 SpdyHeadersIR
headers(stream_id
);
172 headers
.set_fin(fin
);
173 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
175 memcpy(buffer_
.get(), frame
->data(), framer
.GetHeadersMinimumSize());
176 size_
+= framer
.GetHeadersMinimumSize();
179 virtual void OnWindowUpdate(SpdyStreamId stream_id
, int delta_window_size
) {
183 virtual void OnPushPromise(SpdyStreamId stream_id
,
184 SpdyStreamId promised_stream_id
,
186 SpdyFramer
framer(version_
);
187 framer
.set_enable_compression(false);
188 SpdyPushPromiseIR
push_promise(stream_id
, promised_stream_id
);
189 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePushPromise(push_promise
));
191 memcpy(buffer_
.get(), frame
->data(), framer
.GetPushPromiseMinimumSize());
192 size_
+= framer
.GetPushPromiseMinimumSize();
195 virtual void OnContinuation(SpdyStreamId stream_id
, bool end
) OVERRIDE
{
199 char* ReleaseBuffer() {
201 return buffer_
.release();
204 virtual void OnWindowUpdate(SpdyStreamId stream_id
,
205 uint32 delta_window_size
) OVERRIDE
{
209 size_t size() const {
215 SpdyMajorVersion version_
;
216 scoped_ptr
<char[]> buffer_
;
220 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor
);
224 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil
);
227 class TestSpdyVisitor
: public SpdyFramerVisitorInterface
,
228 public SpdyFramerDebugVisitorInterface
{
230 static const size_t kDefaultHeaderBufferSize
= 16 * 1024 * 1024;
232 explicit TestSpdyVisitor(SpdyMajorVersion version
)
234 use_compression_(false),
237 syn_reply_frame_count_(0),
238 headers_frame_count_(0),
241 settings_ack_sent_(0),
242 settings_ack_received_(0),
243 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 DCHECK_EQ(header_buffer_length_
, parsed_length
);
312 const size_t available
= header_buffer_size_
- header_buffer_length_
;
313 if (len
> available
) {
314 header_buffer_valid_
= false;
317 memcpy(header_buffer_
.get() + header_buffer_length_
, header_data
, len
);
318 header_buffer_length_
+= len
;
322 virtual void OnSynStream(SpdyStreamId stream_id
,
323 SpdyStreamId associated_stream_id
,
324 SpdyPriority priority
,
326 bool unidirectional
) OVERRIDE
{
328 InitHeaderStreaming(SYN_STREAM
, stream_id
);
334 virtual void OnSynReply(SpdyStreamId stream_id
, bool fin
) OVERRIDE
{
335 syn_reply_frame_count_
++;
336 InitHeaderStreaming(SYN_REPLY
, stream_id
);
342 virtual void OnRstStream(SpdyStreamId stream_id
,
343 SpdyRstStreamStatus status
) OVERRIDE
{
347 virtual bool OnRstStreamFrameData(const char* rst_stream_data
,
348 size_t len
) OVERRIDE
{
349 if ((rst_stream_data
!= NULL
) && (len
> 0)) {
350 fin_opaque_data_
+= std::string(rst_stream_data
, len
);
355 virtual void OnSetting(SpdySettingsIds id
,
357 uint32 value
) OVERRIDE
{
361 virtual void OnSettingsAck() OVERRIDE
{
362 DCHECK_GE(4, framer_
.protocol_version());
363 settings_ack_received_
++;
366 virtual void OnSettingsEnd() OVERRIDE
{
367 if (framer_
.protocol_version() < 4) { return; }
368 settings_ack_sent_
++;
371 virtual void OnPing(SpdyPingId unique_id
, bool is_ack
) OVERRIDE
{
375 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id
,
376 SpdyGoAwayStatus status
) OVERRIDE
{
380 virtual void OnHeaders(SpdyStreamId stream_id
, bool fin
, bool end
) OVERRIDE
{
381 headers_frame_count_
++;
382 InitHeaderStreaming(HEADERS
, stream_id
);
388 virtual void OnWindowUpdate(SpdyStreamId stream_id
,
389 uint32 delta_window_size
) OVERRIDE
{
390 last_window_update_stream_
= stream_id
;
391 last_window_update_delta_
= delta_window_size
;
394 virtual void OnPushPromise(SpdyStreamId stream_id
,
395 SpdyStreamId promised_stream_id
,
397 InitHeaderStreaming(PUSH_PROMISE
, stream_id
);
398 last_push_promise_stream_
= stream_id
;
399 last_push_promise_promised_stream_
= promised_stream_id
;
402 virtual void OnContinuation(SpdyStreamId stream_id
, bool end
) OVERRIDE
{
403 continuation_count_
++;
406 virtual void OnSendCompressedFrame(SpdyStreamId stream_id
,
409 size_t frame_len
) OVERRIDE
{
410 last_payload_len_
= payload_len
;
411 last_frame_len_
= frame_len
;
414 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id
,
416 size_t frame_len
) OVERRIDE
{
417 last_frame_len_
= frame_len
;
420 // Convenience function which runs a framer simulation with particular input.
421 void SimulateInFramer(const unsigned char* input
, size_t size
) {
422 framer_
.set_enable_compression(use_compression_
);
423 framer_
.set_visitor(this);
424 size_t input_remaining
= size
;
425 const char* input_ptr
= reinterpret_cast<const char*>(input
);
426 while (input_remaining
> 0 &&
427 framer_
.error_code() == SpdyFramer::SPDY_NO_ERROR
) {
428 // To make the tests more interesting, we feed random (amd small) chunks
429 // into the framer. This simulates getting strange-sized reads from
431 const size_t kMaxReadSize
= 32;
433 (rand() % min(input_remaining
, kMaxReadSize
)) + 1;
434 size_t bytes_processed
= framer_
.ProcessInput(input_ptr
, bytes_read
);
435 input_remaining
-= bytes_processed
;
436 input_ptr
+= bytes_processed
;
440 void InitHeaderStreaming(SpdyFrameType header_control_type
,
441 SpdyStreamId stream_id
) {
442 DCHECK_GE(header_control_type
, FIRST_CONTROL_TYPE
);
443 DCHECK_LE(header_control_type
, LAST_CONTROL_TYPE
);
444 memset(header_buffer_
.get(), 0, header_buffer_size_
);
445 header_buffer_length_
= 0;
446 header_stream_id_
= stream_id
;
447 header_control_type_
= header_control_type
;
448 header_buffer_valid_
= true;
449 DCHECK_NE(header_stream_id_
, SpdyFramer::kInvalidStream
);
452 // Override the default buffer size (16K). Call before using the framer!
453 void set_header_buffer_size(size_t header_buffer_size
) {
454 header_buffer_size_
= header_buffer_size
;
455 header_buffer_
.reset(new char[header_buffer_size
]);
458 static size_t header_data_chunk_max_size() {
459 return SpdyFramer::kHeaderDataChunkMaxSize
;
463 bool use_compression_
;
465 // Counters from the visitor callbacks.
467 int syn_frame_count_
;
468 int syn_reply_frame_count_
;
469 int headers_frame_count_
;
472 int settings_ack_sent_
;
473 int settings_ack_received_
;
474 int continuation_count_
;
475 SpdyStreamId last_window_update_stream_
;
476 uint32 last_window_update_delta_
;
477 SpdyStreamId last_push_promise_stream_
;
478 SpdyStreamId last_push_promise_promised_stream_
;
480 int fin_frame_count_
; // The count of RST_STREAM type frames received.
481 std::string fin_opaque_data_
;
482 int fin_flag_count_
; // The count of frames with the FIN flag set.
483 int zero_length_data_frame_count_
; // The count of zero-length data frames.
484 int control_frame_header_data_count_
; // The count of chunks received.
485 // The count of zero-length control frame header data chunks received.
486 int zero_length_control_frame_header_data_count_
;
487 int data_frame_count_
;
488 size_t last_payload_len_
;
489 size_t last_frame_len_
;
491 // Header block streaming state:
492 scoped_ptr
<char[]> header_buffer_
;
493 size_t header_buffer_length_
;
494 size_t header_buffer_size_
;
495 SpdyStreamId header_stream_id_
;
496 SpdyFrameType header_control_type_
;
497 bool header_buffer_valid_
;
498 SpdyHeaderBlock headers_
;
501 // Retrieves serialized headers from SYN_STREAM frame.
502 // Does not check that the given frame is a SYN_STREAM.
503 base::StringPiece
GetSerializedHeaders(const SpdyFrame
* frame
,
504 const SpdyFramer
& framer
) {
505 return base::StringPiece(frame
->data() + framer
.GetSynStreamMinimumSize(),
506 frame
->size() - framer
.GetSynStreamMinimumSize());
513 using net::test::SetFrameLength
;
514 using net::test::SetFrameFlags
;
515 using net::test::CompareCharArraysWithHexError
;
516 using net::test::SpdyFramerTestUtil
;
517 using net::test::TestSpdyVisitor
;
518 using net::test::GetSerializedHeaders
;
522 class SpdyFramerTest
: public ::testing::TestWithParam
<SpdyMajorVersion
> {
524 virtual void SetUp() {
525 spdy_version_
= GetParam();
526 spdy_version_ch_
= static_cast<unsigned char>(spdy_version_
);
529 void CompareFrame(const string
& description
,
530 const SpdyFrame
& actual_frame
,
531 const unsigned char* expected
,
532 const int expected_len
) {
533 const unsigned char* actual
=
534 reinterpret_cast<const unsigned char*>(actual_frame
.data());
535 CompareCharArraysWithHexError(
536 description
, actual
, actual_frame
.size(), expected
, expected_len
);
539 void CompareFrames(const string
& description
,
540 const SpdyFrame
& expected_frame
,
541 const SpdyFrame
& actual_frame
) {
542 CompareCharArraysWithHexError(
544 reinterpret_cast<const unsigned char*>(expected_frame
.data()),
545 expected_frame
.size(),
546 reinterpret_cast<const unsigned char*>(actual_frame
.data()),
547 actual_frame
.size());
550 // Returns true if the two header blocks have equivalent content.
551 bool CompareHeaderBlocks(const SpdyHeaderBlock
* expected
,
552 const SpdyHeaderBlock
* actual
) {
553 if (expected
->size() != actual
->size()) {
554 LOG(ERROR
) << "Expected " << expected
->size() << " headers; actually got "
555 << actual
->size() << ".";
558 for (SpdyHeaderBlock::const_iterator it
= expected
->begin();
559 it
!= expected
->end();
561 SpdyHeaderBlock::const_iterator it2
= actual
->find(it
->first
);
562 if (it2
== actual
->end()) {
563 LOG(ERROR
) << "Expected header name '" << it
->first
<< "'.";
566 if (it
->second
.compare(it2
->second
) != 0) {
567 LOG(ERROR
) << "Expected header named '" << it
->first
568 << "' to have a value of '" << it
->second
569 << "'. The actual value received was '" << it2
->second
577 void AddSpdySettingFromWireFormat(SettingsMap
* settings
,
580 SettingsFlagsAndId flags_and_id
=
581 SettingsFlagsAndId::FromWireFormat(spdy_version_
, key
);
582 SpdySettingsIds id
= static_cast<SpdySettingsIds
>(flags_and_id
.id());
583 SpdySettingsFlags flags
=
584 static_cast<SpdySettingsFlags
>(flags_and_id
.flags());
585 CHECK(settings
->find(id
) == settings
->end());
586 settings
->insert(std::make_pair(id
, SettingsFlagsAndValue(flags
, value
)));
589 bool IsSpdy2() { return spdy_version_
== SPDY2
; }
590 bool IsSpdy3() { return spdy_version_
== SPDY3
; }
591 bool IsSpdy4() { return spdy_version_
== SPDY4
; }
593 // Version of SPDY protocol to be used.
594 SpdyMajorVersion spdy_version_
;
595 unsigned char spdy_version_ch_
;
598 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
599 INSTANTIATE_TEST_CASE_P(SpdyFramerTests
,
601 ::testing::Values(SPDY2
, SPDY3
, SPDY4
));
603 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
604 TEST_P(SpdyFramerTest
, HeaderBlockInBuffer
) {
605 SpdyFramer
framer(spdy_version_
);
606 framer
.set_enable_compression(false);
608 // Encode the header block into a SynStream frame.
609 SpdySynStreamIR
syn_stream(1);
610 syn_stream
.set_priority(1);
611 syn_stream
.SetHeader("alpha", "beta");
612 syn_stream
.SetHeader("gamma", "charlie");
613 syn_stream
.SetHeader("cookie", "key1=value1; key2=value2");
614 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
615 EXPECT_TRUE(frame
.get() != NULL
);
617 TestSpdyVisitor
visitor(spdy_version_
);
618 visitor
.use_compression_
= false;
619 visitor
.SimulateInFramer(
620 reinterpret_cast<unsigned char*>(frame
->data()),
623 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
624 EXPECT_TRUE(CompareHeaderBlocks(&syn_stream
.name_value_block(),
628 // Test that if there's not a full frame, we fail to parse it.
629 TEST_P(SpdyFramerTest
, UndersizedHeaderBlockInBuffer
) {
630 SpdyFramer
framer(spdy_version_
);
631 framer
.set_enable_compression(false);
633 // Encode the header block into a SynStream frame.
634 SpdySynStreamIR
syn_stream(1);
635 syn_stream
.set_priority(1);
636 syn_stream
.SetHeader("alpha", "beta");
637 syn_stream
.SetHeader("gamma", "charlie");
638 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
639 EXPECT_TRUE(frame
.get() != NULL
);
641 TestSpdyVisitor
visitor(spdy_version_
);
642 visitor
.use_compression_
= false;
643 visitor
.SimulateInFramer(
644 reinterpret_cast<unsigned char*>(frame
->data()),
647 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
648 EXPECT_EQ(0u, visitor
.headers_
.size());
651 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
652 // (but don't crash).
653 TEST_P(SpdyFramerTest
, SynReplyWithStreamIdZero
) {
654 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
655 SpdyFramer
framer(spdy_version_
);
656 framer
.set_visitor(&visitor
);
658 SpdySynReplyIR
syn_reply(0);
659 syn_reply
.SetHeader("alpha", "beta");
660 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeSynReply(syn_reply
));
661 ASSERT_TRUE(frame
.get() != NULL
);
663 // We shouldn't have to read the whole frame before we signal an error.
664 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
665 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
666 EXPECT_TRUE(framer
.HasError());
667 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
668 << SpdyFramer::ErrorCodeToString(framer
.error_code());
671 // Test that if we receive a HEADERS with stream ID zero, we signal an error
672 // (but don't crash).
673 TEST_P(SpdyFramerTest
, HeadersWithStreamIdZero
) {
674 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
675 SpdyFramer
framer(spdy_version_
);
676 framer
.set_visitor(&visitor
);
678 SpdyHeadersIR
headers_ir(0);
679 headers_ir
.SetHeader("alpha", "beta");
680 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeHeaders(headers_ir
));
681 ASSERT_TRUE(frame
.get() != NULL
);
683 // We shouldn't have to read the whole frame before we signal an error.
684 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
685 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
686 EXPECT_TRUE(framer
.HasError());
687 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
688 << SpdyFramer::ErrorCodeToString(framer
.error_code());
691 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
692 // error (but don't crash).
693 TEST_P(SpdyFramerTest
, PushPromiseWithStreamIdZero
) {
694 if (spdy_version_
< SPDY4
) {
698 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
699 SpdyFramer
framer(spdy_version_
);
700 framer
.set_visitor(&visitor
);
702 SpdyPushPromiseIR
push_promise(0, 4);
703 push_promise
.SetHeader("alpha", "beta");
704 scoped_ptr
<SpdySerializedFrame
> frame(
705 framer
.SerializePushPromise(push_promise
));
706 ASSERT_TRUE(frame
.get() != NULL
);
708 // We shouldn't have to read the whole frame before we signal an error.
709 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
710 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
711 EXPECT_TRUE(framer
.HasError());
712 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
713 << SpdyFramer::ErrorCodeToString(framer
.error_code());
716 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
717 // signal an error (but don't crash).
718 TEST_P(SpdyFramerTest
, PushPromiseWithPromisedStreamIdZero
) {
719 if (spdy_version_
< SPDY4
) {
723 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
724 SpdyFramer
framer(spdy_version_
);
725 framer
.set_visitor(&visitor
);
727 SpdyPushPromiseIR
push_promise(3, 0);
728 push_promise
.SetHeader("alpha", "beta");
729 scoped_ptr
<SpdySerializedFrame
> frame(
730 framer
.SerializePushPromise(push_promise
));
731 ASSERT_TRUE(frame
.get() != NULL
);
733 // We shouldn't have to read the whole frame before we signal an error.
734 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
735 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
736 EXPECT_TRUE(framer
.HasError());
737 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
738 << SpdyFramer::ErrorCodeToString(framer
.error_code());
741 TEST_P(SpdyFramerTest
, DuplicateHeader
) {
742 if (spdy_version_
>= 4) {
743 // TODO(jgraettinger): Punting on this because we haven't determined
744 // whether duplicate HPACK headers other than Cookie are an error.
745 // If they are, this will need to be updated to use HpackOutputStream.
748 SpdyFramer
framer(spdy_version_
);
749 // Frame builder with plentiful buffer size.
750 SpdyFrameBuilder
frame(1024);
751 if (spdy_version_
< 4) {
752 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
753 frame
.WriteUInt32(3); // stream_id
754 frame
.WriteUInt32(0); // associated stream id
755 frame
.WriteUInt16(0); // Priority.
757 frame
.WriteFramePrefix(framer
, HEADERS
, HEADERS_FLAG_PRIORITY
, 3);
758 frame
.WriteUInt32(framer
.GetHighestPriority());
762 frame
.WriteUInt16(2); // Number of headers.
763 frame
.WriteString("name");
764 frame
.WriteString("value1");
765 frame
.WriteString("name");
766 frame
.WriteString("value2");
768 frame
.WriteUInt32(2); // Number of headers.
769 frame
.WriteStringPiece32("name");
770 frame
.WriteStringPiece32("value1");
771 frame
.WriteStringPiece32("name");
772 frame
.WriteStringPiece32("value2");
775 frame
.RewriteLength(framer
);
777 SpdyHeaderBlock new_headers
;
778 framer
.set_enable_compression(false);
779 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
780 base::StringPiece serialized_headers
=
781 GetSerializedHeaders(control_frame
.get(), framer
);
782 // This should fail because duplicate headers are verboten by the spec.
783 EXPECT_FALSE(framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
784 serialized_headers
.size(),
788 TEST_P(SpdyFramerTest
, MultiValueHeader
) {
789 SpdyFramer
framer(spdy_version_
);
790 // Frame builder with plentiful buffer size.
791 SpdyFrameBuilder
frame(1024);
792 if (spdy_version_
< 4) {
793 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
794 frame
.WriteUInt32(3); // stream_id
795 frame
.WriteUInt32(0); // associated stream id
796 frame
.WriteUInt16(0); // Priority.
798 frame
.WriteFramePrefix(framer
,
800 HEADERS_FLAG_PRIORITY
| HEADERS_FLAG_END_HEADERS
,
802 frame
.WriteUInt32(framer
.GetHighestPriority());
805 string
value("value1\0value2", 13);
807 frame
.WriteUInt16(1); // Number of headers.
808 frame
.WriteString("name");
809 frame
.WriteString(value
);
810 } else if (spdy_version_
>= 4) {
811 HpackOutputStream
output_stream(1024);
812 output_stream
.AppendLiteralHeaderNoIndexingWithName("name", value
);
814 output_stream
.TakeString(&buffer
);
815 frame
.WriteBytes(&buffer
[0], buffer
.size());
817 frame
.WriteUInt32(1); // Number of headers.
818 frame
.WriteStringPiece32("name");
819 frame
.WriteStringPiece32(value
);
822 frame
.RewriteLength(framer
);
824 framer
.set_enable_compression(false);
825 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
827 TestSpdyVisitor
visitor(spdy_version_
);
828 visitor
.use_compression_
= false;
829 visitor
.SimulateInFramer(
830 reinterpret_cast<unsigned char*>(control_frame
->data()),
831 control_frame
->size());
833 EXPECT_THAT(visitor
.headers_
, ElementsAre(
834 Pair("name", value
)));
837 TEST_P(SpdyFramerTest
, BasicCompression
) {
838 if (spdy_version_
>= 4) {
839 // Deflate compression doesn't apply to HPACK.
842 scoped_ptr
<TestSpdyVisitor
> visitor(new TestSpdyVisitor(spdy_version_
));
843 SpdyFramer
framer(spdy_version_
);
844 framer
.set_debug_visitor(visitor
.get());
845 SpdySynStreamIR
syn_stream(1);
846 syn_stream
.set_priority(1);
847 syn_stream
.SetHeader("server", "SpdyServer 1.0");
848 syn_stream
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
849 syn_stream
.SetHeader("status", "200");
850 syn_stream
.SetHeader("version", "HTTP/1.1");
851 syn_stream
.SetHeader("content-type", "text/html");
852 syn_stream
.SetHeader("content-length", "12");
853 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeSynStream(syn_stream
));
854 size_t uncompressed_size1
= visitor
->last_payload_len_
;
855 size_t compressed_size1
=
856 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
858 EXPECT_EQ(139u, uncompressed_size1
);
859 #if defined(USE_SYSTEM_ZLIB)
860 EXPECT_EQ(155u, compressed_size1
);
861 #else // !defined(USE_SYSTEM_ZLIB)
862 EXPECT_EQ(135u, compressed_size1
);
863 #endif // !defined(USE_SYSTEM_ZLIB)
865 EXPECT_EQ(165u, uncompressed_size1
);
866 #if defined(USE_SYSTEM_ZLIB)
867 EXPECT_EQ(181u, compressed_size1
);
868 #else // !defined(USE_SYSTEM_ZLIB)
869 EXPECT_EQ(117u, compressed_size1
);
870 #endif // !defined(USE_SYSTEM_ZLIB)
872 scoped_ptr
<SpdyFrame
> frame2(framer
.SerializeSynStream(syn_stream
));
873 size_t uncompressed_size2
= visitor
->last_payload_len_
;
874 size_t compressed_size2
=
875 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
877 // Expect the second frame to be more compact than the first.
878 EXPECT_LE(frame2
->size(), frame1
->size());
880 // Decompress the first frame
881 scoped_ptr
<SpdyFrame
> frame3(SpdyFramerTestUtil::DecompressFrame(
882 &framer
, *frame1
.get()));
884 // Decompress the second frame
885 visitor
.reset(new TestSpdyVisitor(spdy_version_
));
886 framer
.set_debug_visitor(visitor
.get());
887 scoped_ptr
<SpdyFrame
> frame4(SpdyFramerTestUtil::DecompressFrame(
888 &framer
, *frame2
.get()));
889 size_t uncompressed_size4
=
890 frame4
->size() - framer
.GetSynStreamMinimumSize();
891 size_t compressed_size4
=
892 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
894 EXPECT_EQ(139u, uncompressed_size4
);
895 #if defined(USE_SYSTEM_ZLIB)
896 EXPECT_EQ(149u, compressed_size4
);
897 #else // !defined(USE_SYSTEM_ZLIB)
898 EXPECT_EQ(101u, compressed_size4
);
899 #endif // !defined(USE_SYSTEM_ZLIB)
901 EXPECT_EQ(165u, uncompressed_size4
);
902 #if defined(USE_SYSTEM_ZLIB)
903 EXPECT_EQ(175u, compressed_size4
);
904 #else // !defined(USE_SYSTEM_ZLIB)
905 EXPECT_EQ(102u, compressed_size4
);
906 #endif // !defined(USE_SYSTEM_ZLIB)
909 EXPECT_EQ(uncompressed_size1
, uncompressed_size2
);
910 EXPECT_EQ(uncompressed_size1
, uncompressed_size4
);
911 EXPECT_EQ(compressed_size2
, compressed_size4
);
913 // Expect frames 3 & 4 to be the same.
914 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *frame4
);
916 // Expect frames 3 to be the same as a uncompressed frame created
918 framer
.set_enable_compression(false);
919 scoped_ptr
<SpdyFrame
> uncompressed_frame(
920 framer
.SerializeSynStream(syn_stream
));
921 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *uncompressed_frame
);
924 TEST_P(SpdyFramerTest
, CompressEmptyHeaders
) {
925 // See crbug.com/172383
926 SpdySynStreamIR
syn_stream(1);
927 syn_stream
.SetHeader("server", "SpdyServer 1.0");
928 syn_stream
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
929 syn_stream
.SetHeader("status", "200");
930 syn_stream
.SetHeader("version", "HTTP/1.1");
931 syn_stream
.SetHeader("content-type", "text/html");
932 syn_stream
.SetHeader("content-length", "12");
933 syn_stream
.SetHeader("x-empty-header", "");
935 SpdyFramer
framer(spdy_version_
);
936 framer
.set_enable_compression(true);
937 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeSynStream(syn_stream
));
940 TEST_P(SpdyFramerTest
, Basic
) {
941 const unsigned char kV2Input
[] = {
942 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
943 0x00, 0x00, 0x00, 0x14,
944 0x00, 0x00, 0x00, 0x01,
945 0x00, 0x00, 0x00, 0x00,
946 0x00, 0x00, 0x00, 0x01,
947 0x00, 0x02, 'h', 'h',
948 0x00, 0x02, 'v', 'v',
950 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
951 0x00, 0x00, 0x00, 0x18,
952 0x00, 0x00, 0x00, 0x01,
953 0x00, 0x00, 0x00, 0x02,
954 0x00, 0x02, 'h', '2',
955 0x00, 0x02, 'v', '2',
956 0x00, 0x02, 'h', '3',
957 0x00, 0x02, 'v', '3',
959 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
960 0x00, 0x00, 0x00, 0x0c,
961 0xde, 0xad, 0xbe, 0xef,
962 0xde, 0xad, 0xbe, 0xef,
963 0xde, 0xad, 0xbe, 0xef,
965 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
966 0x00, 0x00, 0x00, 0x0c,
967 0x00, 0x00, 0x00, 0x03,
968 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x00, 0x00, 0x00,
971 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
972 0x00, 0x00, 0x00, 0x08,
973 0xde, 0xad, 0xbe, 0xef,
974 0xde, 0xad, 0xbe, 0xef,
976 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
977 0x00, 0x00, 0x00, 0x04,
978 0xde, 0xad, 0xbe, 0xef,
980 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
981 0x00, 0x00, 0x00, 0x08,
982 0x00, 0x00, 0x00, 0x01,
983 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
986 0x00, 0x00, 0x00, 0x00,
988 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
989 0x00, 0x00, 0x00, 0x08,
990 0x00, 0x00, 0x00, 0x03,
991 0x00, 0x00, 0x00, 0x00,
994 const unsigned char kV3Input
[] = {
995 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
996 0x00, 0x00, 0x00, 0x1a,
997 0x00, 0x00, 0x00, 0x01,
998 0x00, 0x00, 0x00, 0x00,
999 0x00, 0x00, 0x00, 0x00,
1000 0x00, 0x01, 0x00, 0x00,
1001 0x00, 0x02, 'h', 'h',
1002 0x00, 0x00, 0x00, 0x02,
1005 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
1006 0x00, 0x00, 0x00, 0x20,
1007 0x00, 0x00, 0x00, 0x01,
1008 0x00, 0x00, 0x00, 0x02,
1009 0x00, 0x00, 0x00, 0x02,
1011 0x00, 0x00, 0x00, 0x02,
1012 'v', '2', 0x00, 0x00,
1013 0x00, 0x02, 'h', '3',
1014 0x00, 0x00, 0x00, 0x02,
1017 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1018 0x00, 0x00, 0x00, 0x0c,
1019 0xde, 0xad, 0xbe, 0xef,
1020 0xde, 0xad, 0xbe, 0xef,
1021 0xde, 0xad, 0xbe, 0xef,
1023 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1024 0x00, 0x00, 0x00, 0x0e,
1025 0x00, 0x00, 0x00, 0x03,
1026 0x00, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00,
1030 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1031 0x00, 0x00, 0x00, 0x08,
1032 0xde, 0xad, 0xbe, 0xef,
1033 0xde, 0xad, 0xbe, 0xef,
1035 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1036 0x00, 0x00, 0x00, 0x04,
1037 0xde, 0xad, 0xbe, 0xef,
1039 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1040 0x00, 0x00, 0x00, 0x08,
1041 0x00, 0x00, 0x00, 0x01,
1042 0x00, 0x00, 0x00, 0x00,
1044 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1045 0x00, 0x00, 0x00, 0x00,
1047 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1048 0x00, 0x00, 0x00, 0x08,
1049 0x00, 0x00, 0x00, 0x03,
1050 0x00, 0x00, 0x00, 0x00,
1053 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1054 // HEADERS frames with PRIORITY and END_HEADERS set.
1055 const unsigned char kV4Input
[] = {
1056 0x00, 0x0d, 0x08, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1057 0x00, 0x00, 0x00, 0x01, // Stream 1
1058 0x00, 0x00, 0x00, 0x00, // Priority 0
1059 0x82, // :method: GET
1061 0x00, 0x09, 0x08, 0x04, // HEADERS: END_HEADERS
1062 0x00, 0x00, 0x00, 0x01, // Stream 1
1063 0x8c, // :status: 200
1065 0x00, 0x14, 0x00, 0x00, // DATA on Stream #1
1066 0x00, 0x00, 0x00, 0x01,
1067 0xde, 0xad, 0xbe, 0xef,
1068 0xde, 0xad, 0xbe, 0xef,
1069 0xde, 0xad, 0xbe, 0xef,
1071 0x00, 0x0d, 0x08, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1072 0x00, 0x00, 0x00, 0x03, // Stream 3
1073 0x00, 0x00, 0x00, 0x00, // Priority 0
1074 0x82, // :method: GET
1076 0x00, 0x10, 0x00, 0x00, // DATA on Stream #3
1077 0x00, 0x00, 0x00, 0x03,
1078 0xde, 0xad, 0xbe, 0xef,
1079 0xde, 0xad, 0xbe, 0xef,
1081 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1
1082 0x00, 0x00, 0x00, 0x01,
1083 0xde, 0xad, 0xbe, 0xef,
1085 0x00, 0x0c, 0x03, 0x00, // RST_STREAM on Stream #1
1086 0x00, 0x00, 0x00, 0x01,
1087 0x00, 0x00, 0x00, 0x00,
1089 0x00, 0x08, 0x00, 0x00, // DATA on Stream #3
1090 0x00, 0x00, 0x00, 0x03,
1092 0x00, 0x17, 0x03, 0x00, // RST_STREAM on Stream #3
1093 0x00, 0x00, 0x00, 0x03,
1094 0x00, 0x00, 0x00, 0x00,
1095 0x52, 0x45, 0x53, 0x45, // opaque data
1096 0x54, 0x53, 0x54, 0x52,
1100 TestSpdyVisitor
visitor(spdy_version_
);
1102 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1103 } else if (IsSpdy3()) {
1104 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1106 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1109 EXPECT_EQ(2, visitor
.syn_frame_count_
);
1110 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1111 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1112 EXPECT_EQ(24, visitor
.data_bytes_
);
1114 EXPECT_EQ(0, visitor
.error_count_
);
1115 EXPECT_EQ(2, visitor
.fin_frame_count_
);
1118 base::StringPiece reset_stream
= "RESETSTREAM";
1119 EXPECT_EQ(reset_stream
, visitor
.fin_opaque_data_
);
1121 EXPECT_TRUE(visitor
.fin_opaque_data_
.empty());
1124 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1125 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
1126 EXPECT_EQ(4, visitor
.data_frame_count_
);
1127 visitor
.fin_opaque_data_
.clear();
1130 // Test that the FIN flag on a data frame signifies EOF.
1131 TEST_P(SpdyFramerTest
, FinOnDataFrame
) {
1132 const unsigned char kV2Input
[] = {
1133 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1134 0x00, 0x00, 0x00, 0x14,
1135 0x00, 0x00, 0x00, 0x01,
1136 0x00, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x01,
1138 0x00, 0x02, 'h', 'h',
1139 0x00, 0x02, 'v', 'v',
1141 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1142 0x00, 0x00, 0x00, 0x10,
1143 0x00, 0x00, 0x00, 0x01,
1144 0x00, 0x00, 0x00, 0x01,
1145 0x00, 0x02, 'a', 'a',
1146 0x00, 0x02, 'b', 'b',
1148 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1149 0x00, 0x00, 0x00, 0x0c,
1150 0xde, 0xad, 0xbe, 0xef,
1151 0xde, 0xad, 0xbe, 0xef,
1152 0xde, 0xad, 0xbe, 0xef,
1154 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1155 0x01, 0x00, 0x00, 0x04,
1156 0xde, 0xad, 0xbe, 0xef,
1158 const unsigned char kV3Input
[] = {
1159 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1160 0x00, 0x00, 0x00, 0x1a,
1161 0x00, 0x00, 0x00, 0x01,
1162 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x00,
1164 0x00, 0x01, 0x00, 0x00,
1165 0x00, 0x02, 'h', 'h',
1166 0x00, 0x00, 0x00, 0x02,
1169 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1170 0x00, 0x00, 0x00, 0x14,
1171 0x00, 0x00, 0x00, 0x01,
1172 0x00, 0x00, 0x00, 0x01,
1173 0x00, 0x00, 0x00, 0x02,
1174 'a', 'a', 0x00, 0x00,
1175 0x00, 0x02, 'b', 'b',
1177 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1178 0x00, 0x00, 0x00, 0x0c,
1179 0xde, 0xad, 0xbe, 0xef,
1180 0xde, 0xad, 0xbe, 0xef,
1181 0xde, 0xad, 0xbe, 0xef,
1183 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1184 0x01, 0x00, 0x00, 0x04,
1185 0xde, 0xad, 0xbe, 0xef,
1188 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1189 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1190 const unsigned char kV4Input
[] = {
1191 0x00, 0x0d, 0x08, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1192 0x00, 0x00, 0x00, 0x01, // Stream 1
1193 0x00, 0x00, 0x00, 0x00, // Priority 0
1194 0x82, // :method: GET
1196 0x00, 0x09, 0x08, 0x04, // HEADERS: END_HEADERS
1197 0x00, 0x00, 0x00, 0x01, // Stream 1
1198 0x8c, // :status: 200
1200 0x00, 0x14, 0x00, 0x00, // DATA on Stream #1
1201 0x00, 0x00, 0x00, 0x01,
1202 0xde, 0xad, 0xbe, 0xef,
1203 0xde, 0xad, 0xbe, 0xef,
1204 0xde, 0xad, 0xbe, 0xef,
1206 0x00, 0x0c, 0x00, 0x01, // DATA on Stream #1, with FIN
1207 0x00, 0x00, 0x00, 0x01,
1208 0xde, 0xad, 0xbe, 0xef,
1211 TestSpdyVisitor
visitor(spdy_version_
);
1213 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1214 } else if (IsSpdy3()) {
1215 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1217 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1220 EXPECT_EQ(0, visitor
.error_count_
);
1221 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1223 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1224 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1226 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1227 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1229 EXPECT_EQ(16, visitor
.data_bytes_
);
1230 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1231 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1232 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1233 EXPECT_EQ(2, visitor
.data_frame_count_
);
1236 // Test that the FIN flag on a SYN reply frame signifies EOF.
1237 TEST_P(SpdyFramerTest
, FinOnSynReplyFrame
) {
1238 const unsigned char kV2Input
[] = {
1239 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1240 0x00, 0x00, 0x00, 0x14,
1241 0x00, 0x00, 0x00, 0x01,
1242 0x00, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x01,
1244 0x00, 0x02, 'h', 'h',
1245 0x00, 0x02, 'v', 'v',
1247 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1248 0x01, 0x00, 0x00, 0x10,
1249 0x00, 0x00, 0x00, 0x01,
1250 0x00, 0x00, 0x00, 0x01,
1251 0x00, 0x02, 'a', 'a',
1252 0x00, 0x02, 'b', 'b',
1254 const unsigned char kV3Input
[] = {
1255 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1256 0x00, 0x00, 0x00, 0x1a,
1257 0x00, 0x00, 0x00, 0x01,
1258 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x01, 0x00, 0x00,
1261 0x00, 0x02, 'h', 'h',
1262 0x00, 0x00, 0x00, 0x02,
1265 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1266 0x01, 0x00, 0x00, 0x14,
1267 0x00, 0x00, 0x00, 0x01,
1268 0x00, 0x00, 0x00, 0x01,
1269 0x00, 0x00, 0x00, 0x02,
1270 'a', 'a', 0x00, 0x00,
1271 0x00, 0x02, 'b', 'b',
1274 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1275 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1276 const unsigned char kV4Input
[] = {
1277 0x00, 0x0d, 0x08, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1278 0x00, 0x00, 0x00, 0x01, // Stream 1
1279 0x00, 0x00, 0x00, 0x00, // Priority 0
1280 0x82, // :method: GET
1282 0x00, 0x09, 0x08, 0x05, // HEADERS: FIN | END_HEADERS
1283 0x00, 0x00, 0x00, 0x01, // Stream 1
1284 0x8c, // :status: 200
1287 TestSpdyVisitor
visitor(spdy_version_
);
1289 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1290 } else if (IsSpdy3()) {
1291 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1293 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1296 EXPECT_EQ(0, visitor
.error_count_
);
1297 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1299 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1300 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1302 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1303 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1305 EXPECT_EQ(0, visitor
.data_bytes_
);
1306 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1307 EXPECT_EQ(1, visitor
.fin_flag_count_
);
1308 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1309 EXPECT_EQ(0, visitor
.data_frame_count_
);
1312 TEST_P(SpdyFramerTest
, HeaderCompression
) {
1313 if (spdy_version_
>= 4) {
1314 // Deflate compression doesn't apply to HPACK.
1317 SpdyFramer
send_framer(spdy_version_
);
1318 SpdyFramer
recv_framer(spdy_version_
);
1320 send_framer
.set_enable_compression(true);
1321 recv_framer
.set_enable_compression(true);
1323 const char kHeader1
[] = "header1";
1324 const char kHeader2
[] = "header2";
1325 const char kHeader3
[] = "header3";
1326 const char kValue1
[] = "value1";
1327 const char kValue2
[] = "value2";
1328 const char kValue3
[] = "value3";
1331 SpdyHeaderBlock block
;
1332 block
[kHeader1
] = kValue1
;
1333 block
[kHeader2
] = kValue2
;
1334 SpdySynStreamIR
syn_ir_1(1);
1335 syn_ir_1
.set_name_value_block(block
);
1336 scoped_ptr
<SpdyFrame
> syn_frame_1(send_framer
.SerializeFrame(syn_ir_1
));
1337 EXPECT_TRUE(syn_frame_1
.get() != NULL
);
1340 block
[kHeader3
] = kValue3
;
1341 SpdySynStreamIR
syn_stream(3);
1342 syn_stream
.set_name_value_block(block
);
1343 scoped_ptr
<SpdyFrame
> syn_frame_2(send_framer
.SerializeSynStream(syn_stream
));
1344 EXPECT_TRUE(syn_frame_2
.get() != NULL
);
1346 // Now start decompressing
1347 scoped_ptr
<SpdyFrame
> decompressed
;
1348 scoped_ptr
<SpdyFrame
> uncompressed
;
1349 base::StringPiece serialized_headers
;
1350 SpdyHeaderBlock decompressed_headers
;
1352 // Decompress SYN_STREAM #1
1353 decompressed
.reset(SpdyFramerTestUtil::DecompressFrame(
1354 &recv_framer
, *syn_frame_1
.get()));
1355 EXPECT_TRUE(decompressed
.get() != NULL
);
1356 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1357 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1358 serialized_headers
.size(),
1359 &decompressed_headers
));
1360 EXPECT_EQ(2u, decompressed_headers
.size());
1361 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1362 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1364 // Decompress SYN_STREAM #2
1365 decompressed
.reset(SpdyFramerTestUtil::DecompressFrame(
1366 &recv_framer
, *syn_frame_2
.get()));
1367 EXPECT_TRUE(decompressed
.get() != NULL
);
1368 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1369 decompressed_headers
.clear();
1370 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1371 serialized_headers
.size(),
1372 &decompressed_headers
));
1373 EXPECT_EQ(3u, decompressed_headers
.size());
1374 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1375 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1376 EXPECT_EQ(kValue3
, decompressed_headers
[kHeader3
]);
1379 // Verify we don't leak when we leave streams unclosed
1380 TEST_P(SpdyFramerTest
, UnclosedStreamDataCompressors
) {
1381 SpdyFramer
send_framer(spdy_version_
);
1383 send_framer
.set_enable_compression(true);
1385 const char kHeader1
[] = "header1";
1386 const char kHeader2
[] = "header2";
1387 const char kValue1
[] = "value1";
1388 const char kValue2
[] = "value2";
1390 SpdySynStreamIR
syn_stream(1);
1391 syn_stream
.SetHeader(kHeader1
, kValue1
);
1392 syn_stream
.SetHeader(kHeader2
, kValue2
);
1393 scoped_ptr
<SpdyFrame
> syn_frame(send_framer
.SerializeSynStream(syn_stream
));
1394 EXPECT_TRUE(syn_frame
.get() != NULL
);
1396 StringPiece bytes
= "this is a test test test test test!";
1397 net::SpdyDataIR
data_ir(1, bytes
);
1398 data_ir
.set_fin(true);
1399 scoped_ptr
<SpdyFrame
> send_frame(send_framer
.SerializeData(data_ir
));
1400 EXPECT_TRUE(send_frame
.get() != NULL
);
1402 // Run the inputs through the framer.
1403 TestSpdyVisitor
visitor(spdy_version_
);
1404 visitor
.use_compression_
= true;
1405 const unsigned char* data
;
1406 data
= reinterpret_cast<const unsigned char*>(syn_frame
->data());
1407 visitor
.SimulateInFramer(data
, syn_frame
->size());
1408 data
= reinterpret_cast<const unsigned char*>(send_frame
->data());
1409 visitor
.SimulateInFramer(data
, send_frame
->size());
1411 EXPECT_EQ(0, visitor
.error_count_
);
1412 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1413 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1414 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1415 EXPECT_EQ(bytes
.size(), static_cast<unsigned>(visitor
.data_bytes_
));
1416 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1417 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1418 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1419 EXPECT_EQ(1, visitor
.data_frame_count_
);
1422 // Verify we can decompress the stream even if handed over to the
1423 // framer 1 byte at a time.
1424 TEST_P(SpdyFramerTest
, UnclosedStreamDataCompressorsOneByteAtATime
) {
1425 SpdyFramer
send_framer(spdy_version_
);
1427 send_framer
.set_enable_compression(true);
1429 const char kHeader1
[] = "header1";
1430 const char kHeader2
[] = "header2";
1431 const char kValue1
[] = "value1";
1432 const char kValue2
[] = "value2";
1434 SpdySynStreamIR
syn_stream(1);
1435 syn_stream
.SetHeader(kHeader1
, kValue1
);
1436 syn_stream
.SetHeader(kHeader2
, kValue2
);
1437 scoped_ptr
<SpdyFrame
> syn_frame(send_framer
.SerializeSynStream(syn_stream
));
1438 EXPECT_TRUE(syn_frame
.get() != NULL
);
1440 const char bytes
[] = "this is a test test test test test!";
1441 net::SpdyDataIR
data_ir(1, StringPiece(bytes
, arraysize(bytes
)));
1442 data_ir
.set_fin(true);
1443 scoped_ptr
<SpdyFrame
> send_frame(send_framer
.SerializeData(data_ir
));
1444 EXPECT_TRUE(send_frame
.get() != NULL
);
1446 // Run the inputs through the framer.
1447 TestSpdyVisitor
visitor(spdy_version_
);
1448 visitor
.use_compression_
= true;
1449 const unsigned char* data
;
1450 data
= reinterpret_cast<const unsigned char*>(syn_frame
->data());
1451 for (size_t idx
= 0; idx
< syn_frame
->size(); ++idx
) {
1452 visitor
.SimulateInFramer(data
+ idx
, 1);
1453 ASSERT_EQ(0, visitor
.error_count_
);
1455 data
= reinterpret_cast<const unsigned char*>(send_frame
->data());
1456 for (size_t idx
= 0; idx
< send_frame
->size(); ++idx
) {
1457 visitor
.SimulateInFramer(data
+ idx
, 1);
1458 ASSERT_EQ(0, visitor
.error_count_
);
1461 EXPECT_EQ(0, visitor
.error_count_
);
1462 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1463 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1464 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1465 EXPECT_EQ(arraysize(bytes
), static_cast<unsigned>(visitor
.data_bytes_
));
1466 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1467 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1468 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1469 EXPECT_EQ(1, visitor
.data_frame_count_
);
1472 TEST_P(SpdyFramerTest
, WindowUpdateFrame
) {
1473 SpdyFramer
framer(spdy_version_
);
1474 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
1475 net::SpdyWindowUpdateIR(1, 0x12345678)));
1477 const char kDescription
[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1478 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1479 0x80, spdy_version_ch_
, 0x00, 0x09,
1480 0x00, 0x00, 0x00, 0x08,
1481 0x00, 0x00, 0x00, 0x01,
1482 0x12, 0x34, 0x56, 0x78
1484 const unsigned char kV4FrameData
[] = {
1485 0x00, 0x0c, 0x09, 0x00,
1486 0x00, 0x00, 0x00, 0x01,
1487 0x12, 0x34, 0x56, 0x78
1491 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1493 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1497 TEST_P(SpdyFramerTest
, CreateDataFrame
) {
1498 SpdyFramer
framer(spdy_version_
);
1501 const char kDescription
[] = "'hello' data frame, no FIN";
1502 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1503 0x00, 0x00, 0x00, 0x01,
1504 0x00, 0x00, 0x00, 0x05,
1508 const unsigned char kV4FrameData
[] = {
1509 0x00, 0x0d, 0x00, 0x00,
1510 0x00, 0x00, 0x00, 0x01,
1514 const char bytes
[] = "hello";
1516 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1517 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1520 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1523 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1526 SpdyDataIR
data_header_ir(1);
1527 data_header_ir
.SetDataShallow(base::StringPiece(bytes
, strlen(bytes
)));
1528 frame
.reset(framer
.SerializeDataFrameHeader(data_header_ir
));
1529 CompareCharArraysWithHexError(
1531 reinterpret_cast<const unsigned char*>(frame
->data()),
1532 framer
.GetDataFrameMinimumSize(),
1533 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1534 framer
.GetDataFrameMinimumSize());
1538 const char kDescription
[] = "Data frame with negative data byte, no FIN";
1539 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1540 0x00, 0x00, 0x00, 0x01,
1541 0x00, 0x00, 0x00, 0x01,
1544 const unsigned char kV4FrameData
[] = {
1545 0x00, 0x09, 0x00, 0x00,
1546 0x00, 0x00, 0x00, 0x01,
1549 net::SpdyDataIR
data_ir(1, StringPiece("\xff", 1));
1550 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1553 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1556 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1561 const char kDescription
[] = "'hello' data frame, with FIN";
1562 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1563 0x00, 0x00, 0x00, 0x01,
1564 0x01, 0x00, 0x00, 0x05,
1568 const unsigned char kV4FrameData
[] = {
1569 0x00, 0x0d, 0x00, 0x01,
1570 0x00, 0x00, 0x00, 0x01,
1574 net::SpdyDataIR
data_ir(1, StringPiece("hello", 5));
1575 data_ir
.set_fin(true);
1576 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1579 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1582 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1587 const char kDescription
[] = "Empty data frame";
1588 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1589 0x00, 0x00, 0x00, 0x01,
1590 0x00, 0x00, 0x00, 0x00,
1592 const unsigned char kV4FrameData
[] = {
1593 0x00, 0x08, 0x00, 0x00,
1594 0x00, 0x00, 0x00, 0x01,
1596 net::SpdyDataIR
data_ir(1, StringPiece());
1597 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1600 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1603 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1608 const char kDescription
[] = "Data frame with max stream ID";
1609 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1610 0x7f, 0xff, 0xff, 0xff,
1611 0x01, 0x00, 0x00, 0x05,
1615 const unsigned char kV4FrameData
[] = {
1616 0x00, 0x0d, 0x00, 0x01,
1617 0x7f, 0xff, 0xff, 0xff,
1621 net::SpdyDataIR
data_ir(0x7fffffff, "hello");
1622 data_ir
.set_fin(true);
1623 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1626 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1629 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1634 // This test does not apply to SPDY 4 because the max frame size is smaller
1636 const char kDescription
[] = "Large data frame";
1637 const int kDataSize
= 4 * 1024 * 1024; // 4 MB
1638 const string
kData(kDataSize
, 'A');
1639 const unsigned char kFrameHeader
[] = {
1640 0x00, 0x00, 0x00, 0x01,
1641 0x01, 0x40, 0x00, 0x00,
1644 const int kFrameSize
= arraysize(kFrameHeader
) + kDataSize
;
1645 scoped_ptr
<unsigned char[]> expected_frame_data(
1646 new unsigned char[kFrameSize
]);
1647 memcpy(expected_frame_data
.get(), kFrameHeader
, arraysize(kFrameHeader
));
1648 memset(expected_frame_data
.get() + arraysize(kFrameHeader
), 'A', kDataSize
);
1650 net::SpdyDataIR
data_ir(1, StringPiece(kData
.data(), kData
.size()));
1651 data_ir
.set_fin(true);
1652 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1653 CompareFrame(kDescription
, *frame
, expected_frame_data
.get(), kFrameSize
);
1657 TEST_P(SpdyFramerTest
, CreateSynStreamUncompressed
) {
1658 SpdyFramer
framer(spdy_version_
);
1659 framer
.set_enable_compression(false);
1662 const char kDescription
[] = "SYN_STREAM frame, lowest pri, no FIN";
1664 const unsigned char kPri
= IsSpdy2() ? 0xC0 : 0xE0;
1665 const unsigned char kV2FrameData
[] = {
1666 0x80, spdy_version_ch_
, 0x00, 0x01,
1667 0x00, 0x00, 0x00, 0x20,
1668 0x00, 0x00, 0x00, 0x01,
1669 0x00, 0x00, 0x00, 0x00,
1670 kPri
, 0x00, 0x00, 0x02,
1671 0x00, 0x03, 'b', 'a',
1672 'r', 0x00, 0x03, 'f',
1673 'o', 'o', 0x00, 0x03,
1674 'f', 'o', 'o', 0x00,
1677 const unsigned char kV3FrameData
[] = {
1678 0x80, spdy_version_ch_
, 0x00, 0x01,
1679 0x00, 0x00, 0x00, 0x2a,
1680 0x00, 0x00, 0x00, 0x01,
1681 0x00, 0x00, 0x00, 0x00,
1682 kPri
, 0x00, 0x00, 0x00,
1683 0x00, 0x02, 0x00, 0x00,
1684 0x00, 0x03, 'b', 'a',
1685 'r', 0x00, 0x00, 0x00,
1686 0x03, 'f', 'o', 'o',
1687 0x00, 0x00, 0x00, 0x03,
1688 'f', 'o', 'o', 0x00,
1689 0x00, 0x00, 0x03, 'b',
1692 const unsigned char kV4FrameData
[] = {
1693 0x00, 0x1e, 0x08, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1694 0x00, 0x00, 0x00, 0x01, // Stream 1
1695 0x00, 0x00, 0x00, 0x07, // Priority 7
1696 0x40, 0x03, 0x62, 0x61, // @.ba
1697 0x72, 0x03, 0x66, 0x6f, // r.fo
1698 0x6f, 0x40, 0x03, 0x66, // o@.f
1699 0x6f, 0x6f, 0x03, 0x62, // oo.b
1702 SpdySynStreamIR
syn_stream(1);
1703 syn_stream
.set_priority(framer
.GetLowestPriority());
1704 syn_stream
.SetHeader("bar", "foo");
1705 syn_stream
.SetHeader("foo", "bar");
1706 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1708 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1709 } else if (IsSpdy3()) {
1710 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1712 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1717 const char kDescription
[] =
1718 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1721 const unsigned char kV2FrameData
[] = {
1722 0x80, spdy_version_ch_
, 0x00, 0x01,
1723 0x01, 0x00, 0x00, 0x1D,
1724 0x7f, 0xff, 0xff, 0xff,
1725 0x7f, 0xff, 0xff, 0xff,
1726 0x00, 0x00, 0x00, 0x02,
1727 0x00, 0x00, 0x00, 0x03,
1728 'f', 'o', 'o', 0x00,
1729 0x03, 'f', 'o', 'o',
1730 0x00, 0x03, 'b', 'a',
1733 const unsigned char kV3FrameData
[] = {
1734 0x80, spdy_version_ch_
, 0x00, 0x01,
1735 0x01, 0x00, 0x00, 0x27,
1736 0x7f, 0xff, 0xff, 0xff,
1737 0x7f, 0xff, 0xff, 0xff,
1738 0x00, 0x00, 0x00, 0x00,
1739 0x00, 0x02, 0x00, 0x00,
1740 0x00, 0x00, 0x00, 0x00,
1741 0x00, 0x03, 'f', 'o',
1742 'o', 0x00, 0x00, 0x00,
1743 0x03, 'f', 'o', 'o',
1744 0x00, 0x00, 0x00, 0x03,
1747 const unsigned char kV4FrameData
[] = {
1748 0x00, 0x1b, 0x08, 0x0d, // HEADERS: PRIORITY | FIN | END_HEADERS
1749 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1750 0x00, 0x00, 0x00, 0x00, // Priority 0
1751 0x40, 0x00, 0x03, 0x66, // @..f
1752 0x6f, 0x6f, 0x40, 0x03, // oo@.
1753 0x66, 0x6f, 0x6f, 0x03, // foo.
1754 0x62, 0x61, 0x72, // bar
1756 SpdySynStreamIR
syn_stream(0x7fffffff);
1757 syn_stream
.set_associated_to_stream_id(0x7fffffff);
1758 syn_stream
.set_priority(framer
.GetHighestPriority());
1759 syn_stream
.set_fin(true);
1760 syn_stream
.SetHeader("", "foo");
1761 syn_stream
.SetHeader("foo", "bar");
1762 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1764 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1765 } else if (IsSpdy3()) {
1766 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1768 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1773 const char kDescription
[] =
1774 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1777 const unsigned char kPri
= IsSpdy2() ? 0x40 : 0x20;
1778 const unsigned char kV2FrameData
[] = {
1779 0x80, spdy_version_ch_
, 0x00, 0x01,
1780 0x01, 0x00, 0x00, 0x1D,
1781 0x7f, 0xff, 0xff, 0xff,
1782 0x7f, 0xff, 0xff, 0xff,
1783 kPri
, 0x00, 0x00, 0x02,
1784 0x00, 0x03, 'b', 'a',
1785 'r', 0x00, 0x03, 'f',
1786 'o', 'o', 0x00, 0x03,
1787 'f', 'o', 'o', 0x00,
1790 const unsigned char kV3FrameData
[] = {
1791 0x80, spdy_version_ch_
, 0x00, 0x01,
1792 0x01, 0x00, 0x00, 0x27,
1793 0x7f, 0xff, 0xff, 0xff,
1794 0x7f, 0xff, 0xff, 0xff,
1795 kPri
, 0x00, 0x00, 0x00,
1796 0x00, 0x02, 0x00, 0x00,
1797 0x00, 0x03, 'b', 'a',
1798 'r', 0x00, 0x00, 0x00,
1799 0x03, 'f', 'o', 'o',
1800 0x00, 0x00, 0x00, 0x03,
1801 'f', 'o', 'o', 0x00,
1804 const unsigned char kV4FrameData
[] = {
1805 0x00, 0x1b, 0x08, 0x0d, // HEADERS: PRIORITY | FIN | END_HEADERS
1806 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1807 0x00, 0x00, 0x00, 0x01, // Priority 1
1808 0x40, 0x03, 0x62, 0x61, // @.ba
1809 0x72, 0x03, 0x66, 0x6f, // r.fo
1810 0x6f, 0x40, 0x03, 0x66, // o@.f
1811 0x6f, 0x6f, 0x00, // oo.
1813 SpdySynStreamIR
syn_stream(0x7fffffff);
1814 syn_stream
.set_associated_to_stream_id(0x7fffffff);
1815 syn_stream
.set_priority(1);
1816 syn_stream
.set_fin(true);
1817 syn_stream
.SetHeader("bar", "foo");
1818 syn_stream
.SetHeader("foo", "");
1819 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1821 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1822 } else if (IsSpdy3()) {
1823 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1825 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1830 // TODO(phajdan.jr): Clean up after we no longer need
1831 // to workaround http://crbug.com/139744.
1832 #if !defined(USE_SYSTEM_ZLIB)
1833 TEST_P(SpdyFramerTest
, CreateSynStreamCompressed
) {
1834 SpdyFramer
framer(spdy_version_
);
1835 framer
.set_enable_compression(true);
1838 const char kDescription
[] =
1839 "SYN_STREAM frame, low pri, no FIN";
1841 const SpdyPriority priority
= IsSpdy2() ? 2 : 4;
1842 const unsigned char kV2FrameData
[] = {
1843 0x80, spdy_version_ch_
, 0x00, 0x01,
1844 0x00, 0x00, 0x00, 0x36,
1845 0x00, 0x00, 0x00, 0x01,
1846 0x00, 0x00, 0x00, 0x00,
1847 0x80, 0x00, 0x38, 0xea,
1848 0xdf, 0xa2, 0x51, 0xb2,
1849 0x62, 0x60, 0x62, 0x60,
1850 0x4e, 0x4a, 0x2c, 0x62,
1851 0x60, 0x06, 0x08, 0xa0,
1852 0xb4, 0xfc, 0x7c, 0x80,
1853 0x00, 0x62, 0x60, 0x4e,
1854 0xcb, 0xcf, 0x67, 0x60,
1855 0x06, 0x08, 0xa0, 0xa4,
1856 0xc4, 0x22, 0x80, 0x00,
1857 0x02, 0x00, 0x00, 0x00,
1860 const unsigned char kV3FrameData
[] = {
1861 0x80, spdy_version_ch_
, 0x00, 0x01,
1862 0x00, 0x00, 0x00, 0x37,
1863 0x00, 0x00, 0x00, 0x01,
1864 0x00, 0x00, 0x00, 0x00,
1865 0x80, 0x00, 0x38, 0xEA,
1866 0xE3, 0xC6, 0xA7, 0xC2,
1867 0x02, 0xE5, 0x0E, 0x50,
1868 0xC2, 0x4B, 0x4A, 0x04,
1869 0xE5, 0x0B, 0x66, 0x80,
1870 0x00, 0x4A, 0xCB, 0xCF,
1871 0x07, 0x08, 0x20, 0x10,
1872 0x95, 0x96, 0x9F, 0x0F,
1873 0xA2, 0x00, 0x02, 0x28,
1874 0x29, 0xB1, 0x08, 0x20,
1875 0x80, 0x00, 0x00, 0x00,
1878 SpdySynStreamIR
syn_stream(1);
1879 syn_stream
.set_priority(priority
);
1880 syn_stream
.SetHeader("bar", "foo");
1881 syn_stream
.SetHeader("foo", "bar");
1882 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1884 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1885 } else if (IsSpdy3()) {
1886 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1888 // Deflate compression doesn't apply to HPACK.
1892 #endif // !defined(USE_SYSTEM_ZLIB)
1894 TEST_P(SpdyFramerTest
, CreateSynReplyUncompressed
) {
1895 SpdyFramer
framer(spdy_version_
);
1896 framer
.set_enable_compression(false);
1899 const char kDescription
[] = "SYN_REPLY frame, no FIN";
1901 const unsigned char kV2FrameData
[] = {
1902 0x80, spdy_version_ch_
, 0x00, 0x02,
1903 0x00, 0x00, 0x00, 0x1C,
1904 0x00, 0x00, 0x00, 0x01,
1905 0x00, 0x00, 0x00, 0x02,
1906 0x00, 0x03, 'b', 'a',
1907 'r', 0x00, 0x03, 'f',
1908 'o', 'o', 0x00, 0x03,
1909 'f', 'o', 'o', 0x00,
1912 const unsigned char kV3FrameData
[] = {
1913 0x80, spdy_version_ch_
, 0x00, 0x02,
1914 0x00, 0x00, 0x00, 0x24,
1915 0x00, 0x00, 0x00, 0x01,
1916 0x00, 0x00, 0x00, 0x02,
1917 0x00, 0x00, 0x00, 0x03,
1918 'b', 'a', 'r', 0x00,
1919 0x00, 0x00, 0x03, 'f',
1920 'o', 'o', 0x00, 0x00,
1921 0x00, 0x03, 'f', 'o',
1922 'o', 0x00, 0x00, 0x00,
1925 const unsigned char kV4FrameData
[] = {
1926 0x00, 0x1a, 0x08, 0x04, // HEADER: END_HEADERS
1927 0x00, 0x00, 0x00, 0x01, // Stream 1
1928 0x40, 0x03, 0x62, 0x61, // @.ba
1929 0x72, 0x03, 0x66, 0x6f, // r.fo
1930 0x6f, 0x40, 0x03, 0x66, // o@.f
1931 0x6f, 0x6f, 0x03, 0x62, // oo.b
1934 SpdySynReplyIR
syn_reply(1);
1935 syn_reply
.SetHeader("bar", "foo");
1936 syn_reply
.SetHeader("foo", "bar");
1937 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
1939 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1940 } else if (IsSpdy3()) {
1941 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1943 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1948 const char kDescription
[] =
1949 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
1951 const unsigned char kV2FrameData
[] = {
1952 0x80, spdy_version_ch_
, 0x00, 0x02,
1953 0x01, 0x00, 0x00, 0x19,
1954 0x7f, 0xff, 0xff, 0xff,
1955 0x00, 0x00, 0x00, 0x02,
1956 0x00, 0x00, 0x00, 0x03,
1957 'f', 'o', 'o', 0x00,
1958 0x03, 'f', 'o', 'o',
1959 0x00, 0x03, 'b', 'a',
1962 const unsigned char kV3FrameData
[] = {
1963 0x80, spdy_version_ch_
, 0x00, 0x02,
1964 0x01, 0x00, 0x00, 0x21,
1965 0x7f, 0xff, 0xff, 0xff,
1966 0x00, 0x00, 0x00, 0x02,
1967 0x00, 0x00, 0x00, 0x00,
1968 0x00, 0x00, 0x00, 0x03,
1969 'f', 'o', 'o', 0x00,
1970 0x00, 0x00, 0x03, 'f',
1971 'o', 'o', 0x00, 0x00,
1972 0x00, 0x03, 'b', 'a',
1975 const unsigned char kV4FrameData
[] = {
1976 0x00, 0x17, 0x08, 0x05, // HEADER: FIN | END_HEADERS
1977 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1978 0x40, 0x00, 0x03, 0x66, // @..f
1979 0x6f, 0x6f, 0x40, 0x03, // oo@.
1980 0x66, 0x6f, 0x6f, 0x03, // foo.
1981 0x62, 0x61, 0x72, // bar
1983 SpdySynReplyIR
syn_reply(0x7fffffff);
1984 syn_reply
.set_fin(true);
1985 syn_reply
.SetHeader("", "foo");
1986 syn_reply
.SetHeader("foo", "bar");
1987 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
1989 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1990 } else if (IsSpdy3()) {
1991 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1993 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1998 const char kDescription
[] =
1999 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2001 const unsigned char kV2FrameData
[] = {
2002 0x80, spdy_version_ch_
, 0x00, 0x02,
2003 0x01, 0x00, 0x00, 0x19,
2004 0x7f, 0xff, 0xff, 0xff,
2005 0x00, 0x00, 0x00, 0x02,
2006 0x00, 0x03, 'b', 'a',
2007 'r', 0x00, 0x03, 'f',
2008 'o', 'o', 0x00, 0x03,
2009 'f', 'o', 'o', 0x00,
2012 const unsigned char kV3FrameData
[] = {
2013 0x80, spdy_version_ch_
, 0x00, 0x02,
2014 0x01, 0x00, 0x00, 0x21,
2015 0x7f, 0xff, 0xff, 0xff,
2016 0x00, 0x00, 0x00, 0x02,
2017 0x00, 0x00, 0x00, 0x03,
2018 'b', 'a', 'r', 0x00,
2019 0x00, 0x00, 0x03, 'f',
2020 'o', 'o', 0x00, 0x00,
2021 0x00, 0x03, 'f', 'o',
2022 'o', 0x00, 0x00, 0x00,
2025 const unsigned char kV4FrameData
[] = {
2026 0x00, 0x17, 0x08, 0x05, // HEADER: FIN | END_HEADERS
2027 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2028 0x40, 0x03, 0x62, 0x61, // @.ba
2029 0x72, 0x03, 0x66, 0x6f, // r.fo
2030 0x6f, 0x40, 0x03, 0x66, // o@.f
2031 0x6f, 0x6f, 0x00, // oo.
2033 SpdySynReplyIR
syn_reply(0x7fffffff);
2034 syn_reply
.set_fin(true);
2035 syn_reply
.SetHeader("bar", "foo");
2036 syn_reply
.SetHeader("foo", "");
2037 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2039 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2040 } else if (IsSpdy3()) {
2041 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2043 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2048 // TODO(phajdan.jr): Clean up after we no longer need
2049 // to workaround http://crbug.com/139744.
2050 #if !defined(USE_SYSTEM_ZLIB)
2051 TEST_P(SpdyFramerTest
, CreateSynReplyCompressed
) {
2052 SpdyFramer
framer(spdy_version_
);
2053 framer
.set_enable_compression(true);
2056 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2058 const unsigned char kV2FrameData
[] = {
2059 0x80, spdy_version_ch_
, 0x00, 0x02,
2060 0x00, 0x00, 0x00, 0x32,
2061 0x00, 0x00, 0x00, 0x01,
2062 0x00, 0x00, 0x38, 0xea,
2063 0xdf, 0xa2, 0x51, 0xb2,
2064 0x62, 0x60, 0x62, 0x60,
2065 0x4e, 0x4a, 0x2c, 0x62,
2066 0x60, 0x06, 0x08, 0xa0,
2067 0xb4, 0xfc, 0x7c, 0x80,
2068 0x00, 0x62, 0x60, 0x4e,
2069 0xcb, 0xcf, 0x67, 0x60,
2070 0x06, 0x08, 0xa0, 0xa4,
2071 0xc4, 0x22, 0x80, 0x00,
2072 0x02, 0x00, 0x00, 0x00,
2075 const unsigned char kV3FrameData
[] = {
2076 0x80, spdy_version_ch_
, 0x00, 0x02,
2077 0x00, 0x00, 0x00, 0x31,
2078 0x00, 0x00, 0x00, 0x01,
2079 0x38, 0xea, 0xe3, 0xc6,
2080 0xa7, 0xc2, 0x02, 0xe5,
2081 0x0e, 0x50, 0xc2, 0x4b,
2082 0x4a, 0x04, 0xe5, 0x0b,
2083 0x66, 0x80, 0x00, 0x4a,
2084 0xcb, 0xcf, 0x07, 0x08,
2085 0x20, 0x10, 0x95, 0x96,
2086 0x9f, 0x0f, 0xa2, 0x00,
2087 0x02, 0x28, 0x29, 0xb1,
2088 0x08, 0x20, 0x80, 0x00,
2089 0x00, 0x00, 0x00, 0xff,
2092 SpdySynReplyIR
syn_reply(1);
2093 syn_reply
.SetHeader("bar", "foo");
2094 syn_reply
.SetHeader("foo", "bar");
2095 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2097 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2098 } else if (IsSpdy3()) {
2099 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2101 // Deflate compression doesn't apply to HPACK.
2105 #endif // !defined(USE_SYSTEM_ZLIB)
2107 TEST_P(SpdyFramerTest
, CreateRstStream
) {
2108 SpdyFramer
framer(spdy_version_
);
2111 const char kDescription
[] = "RST_STREAM frame";
2112 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2113 0x80, spdy_version_ch_
, 0x00, 0x03,
2114 0x00, 0x00, 0x00, 0x08,
2115 0x00, 0x00, 0x00, 0x01,
2116 0x00, 0x00, 0x00, 0x01,
2118 const unsigned char kV4FrameData
[] = {
2119 0x00, 0x0f, 0x03, 0x00,
2120 0x00, 0x00, 0x00, 0x01,
2121 0x00, 0x00, 0x00, 0x01,
2124 net::SpdyRstStreamIR
rst_stream(1, RST_STREAM_PROTOCOL_ERROR
, "RST");
2125 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2127 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2129 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2134 const char kDescription
[] = "RST_STREAM frame with max stream ID";
2135 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2136 0x80, spdy_version_ch_
, 0x00, 0x03,
2137 0x00, 0x00, 0x00, 0x08,
2138 0x7f, 0xff, 0xff, 0xff,
2139 0x00, 0x00, 0x00, 0x01,
2141 const unsigned char kV4FrameData
[] = {
2142 0x00, 0x0c, 0x03, 0x00,
2143 0x7f, 0xff, 0xff, 0xff,
2144 0x00, 0x00, 0x00, 0x01,
2146 net::SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2147 RST_STREAM_PROTOCOL_ERROR
,
2149 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2151 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2153 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2158 const char kDescription
[] = "RST_STREAM frame with max status code";
2159 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2160 0x80, spdy_version_ch_
, 0x00, 0x03,
2161 0x00, 0x00, 0x00, 0x08,
2162 0x7f, 0xff, 0xff, 0xff,
2163 0x00, 0x00, 0x00, 0x06,
2165 const unsigned char kV4FrameData
[] = {
2166 0x00, 0x0c, 0x03, 0x00,
2167 0x7f, 0xff, 0xff, 0xff,
2168 0x00, 0x00, 0x00, 0x06,
2170 net::SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2171 RST_STREAM_INTERNAL_ERROR
,
2173 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2175 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2177 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2182 TEST_P(SpdyFramerTest
, CreateSettings
) {
2183 SpdyFramer
framer(spdy_version_
);
2186 const char kDescription
[] = "Network byte order SETTINGS frame";
2188 const unsigned char kV2FrameData
[] = {
2189 0x80, spdy_version_ch_
, 0x00, 0x04,
2190 0x00, 0x00, 0x00, 0x0c,
2191 0x00, 0x00, 0x00, 0x01,
2192 0x04, 0x03, 0x02, 0x01,
2193 0x0a, 0x0b, 0x0c, 0x0d,
2195 const unsigned char kV3FrameData
[] = {
2196 0x80, spdy_version_ch_
, 0x00, 0x04,
2197 0x00, 0x00, 0x00, 0x0c,
2198 0x00, 0x00, 0x00, 0x01,
2199 0x01, 0x02, 0x03, 0x04,
2200 0x0a, 0x0b, 0x0c, 0x0d,
2202 const unsigned char kV4FrameData
[] = {
2203 0x00, 0x0d, 0x04, 0x00,
2204 0x00, 0x00, 0x00, 0x00,
2205 0x01, 0x0a, 0x0b, 0x0c,
2209 uint32 kValue
= 0x0a0b0c0d;
2210 SpdySettingsIR settings_ir
;
2212 SpdySettingsFlags kFlags
= static_cast<SpdySettingsFlags
>(0x01);
2213 SpdySettingsIds kId
= static_cast<SpdySettingsIds
>(0x020304);
2215 kId
= static_cast<SpdySettingsIds
>(0x01);
2217 SettingsMap settings
;
2218 settings
[kId
] = SettingsFlagsAndValue(kFlags
, kValue
);
2219 EXPECT_EQ(kFlags
, settings
[kId
].first
);
2220 EXPECT_EQ(kValue
, settings
[kId
].second
);
2221 settings_ir
.AddSetting(kId
,
2222 kFlags
& SETTINGS_FLAG_PLEASE_PERSIST
,
2223 kFlags
& SETTINGS_FLAG_PERSISTED
,
2226 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2228 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2229 } else if (IsSpdy3()) {
2230 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2232 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2237 const char kDescription
[] = "Basic SETTINGS frame";
2239 SettingsMap settings
;
2240 AddSpdySettingFromWireFormat(
2241 &settings
, 0x00000000, 0x00000001); // 1st Setting
2242 AddSpdySettingFromWireFormat(
2243 &settings
, 0x01000001, 0x00000002); // 2nd Setting
2244 AddSpdySettingFromWireFormat(
2245 &settings
, 0x02000002, 0x00000003); // 3rd Setting
2246 AddSpdySettingFromWireFormat(
2247 &settings
, 0x03000003, 0xff000004); // 4th Setting
2249 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2250 0x80, spdy_version_ch_
, 0x00, 0x04,
2251 0x00, 0x00, 0x00, 0x24,
2252 0x00, 0x00, 0x00, 0x04,
2253 0x00, 0x00, 0x00, 0x00, // 1st Setting
2254 0x00, 0x00, 0x00, 0x01,
2255 0x01, 0x00, 0x00, 0x01, // 2nd Setting
2256 0x00, 0x00, 0x00, 0x02,
2257 0x02, 0x00, 0x00, 0x02, // 3rd Setting
2258 0x00, 0x00, 0x00, 0x03,
2259 0x03, 0x00, 0x00, 0x03, // 4th Setting
2260 0xff, 0x00, 0x00, 0x04,
2262 const unsigned char kV4FrameData
[] = {
2263 0x00, 0x1c, 0x04, 0x00,
2264 0x00, 0x00, 0x00, 0x00,
2265 0x01, // 1st Setting
2266 0x00, 0x00, 0x00, 0x01,
2267 0x02, // 2nd Setting
2268 0x00, 0x00, 0x00, 0x02,
2269 0x03, // 3rd Setting
2270 0x00, 0x00, 0x00, 0x03,
2271 0x04, // 4th Setting
2272 0xff, 0x00, 0x00, 0x04,
2274 SpdySettingsIR settings_ir
;
2276 for (SettingsMap::const_iterator it
= settings
.begin();
2277 it
!= settings
.end();
2279 settings_ir
.AddSetting(it
->first
,
2280 it
->second
.first
& SETTINGS_FLAG_PLEASE_PERSIST
,
2281 it
->second
.first
& SETTINGS_FLAG_PERSISTED
,
2285 SpdySettingsIds kId
= static_cast<SpdySettingsIds
>(0x01);
2286 settings_ir
.AddSetting(kId
, 0, 0, 0x00000001);
2287 kId
= static_cast<SpdySettingsIds
>(0x02);
2288 settings_ir
.AddSetting(kId
, 0, 0, 0x00000002);
2289 kId
= static_cast<SpdySettingsIds
>(0x03);
2290 settings_ir
.AddSetting(kId
, 0, 0, 0x00000003);
2291 kId
= static_cast<SpdySettingsIds
>(0x04);
2292 settings_ir
.AddSetting(kId
, 0, 0, 0xff000004);
2294 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2296 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2298 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2303 const char kDescription
[] = "Empty SETTINGS frame";
2305 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2306 0x80, spdy_version_ch_
, 0x00, 0x04,
2307 0x00, 0x00, 0x00, 0x04,
2308 0x00, 0x00, 0x00, 0x00,
2310 const unsigned char kV4FrameData
[] = {
2311 0x00, 0x08, 0x04, 0x00,
2312 0x00, 0x00, 0x00, 0x00,
2314 SpdySettingsIR settings_ir
;
2315 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2317 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2319 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2324 TEST_P(SpdyFramerTest
, CreatePingFrame
) {
2325 SpdyFramer
framer(spdy_version_
);
2328 const char kDescription
[] = "PING frame";
2329 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2330 0x80, spdy_version_ch_
, 0x00, 0x06,
2331 0x00, 0x00, 0x00, 0x04,
2332 0x12, 0x34, 0x56, 0x78,
2334 const unsigned char kV4FrameData
[] = {
2335 0x00, 0x10, 0x06, 0x00,
2336 0x00, 0x00, 0x00, 0x00,
2337 0x12, 0x34, 0x56, 0x78,
2338 0x9a, 0xbc, 0xde, 0xff,
2340 const unsigned char kV4FrameDataWithAck
[] = {
2341 0x00, 0x10, 0x06, 0x01,
2342 0x00, 0x00, 0x00, 0x00,
2343 0x12, 0x34, 0x56, 0x78,
2344 0x9a, 0xbc, 0xde, 0xff,
2346 scoped_ptr
<SpdyFrame
> frame
;
2348 const SpdyPingId kPingId
= 0x123456789abcdeffULL
;
2349 SpdyPingIR
ping_ir(kPingId
);
2350 // Tests SpdyPingIR when the ping is not an ack.
2351 ASSERT_FALSE(ping_ir
.is_ack());
2352 frame
.reset(framer
.SerializePing(ping_ir
));
2353 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2355 // Tests SpdyPingIR when the ping is an ack.
2356 ping_ir
.set_is_ack(true);
2357 frame
.reset(framer
.SerializePing(ping_ir
));
2358 CompareFrame(kDescription
, *frame
,
2359 kV4FrameDataWithAck
, arraysize(kV4FrameDataWithAck
));
2362 frame
.reset(framer
.SerializePing(SpdyPingIR(0x12345678ull
)));
2363 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2368 TEST_P(SpdyFramerTest
, CreateGoAway
) {
2369 SpdyFramer
framer(spdy_version_
);
2372 const char kDescription
[] = "GOAWAY frame";
2373 const unsigned char kV2FrameData
[] = {
2374 0x80, spdy_version_ch_
, 0x00, 0x07,
2375 0x00, 0x00, 0x00, 0x04,
2376 0x00, 0x00, 0x00, 0x00, // Stream Id
2378 const unsigned char kV3FrameData
[] = {
2379 0x80, spdy_version_ch_
, 0x00, 0x07,
2380 0x00, 0x00, 0x00, 0x08,
2381 0x00, 0x00, 0x00, 0x00, // Stream Id
2382 0x00, 0x00, 0x00, 0x00, // Status
2384 const unsigned char kV4FrameData
[] = {
2385 0x00, 0x12, 0x07, 0x00,
2386 0x00, 0x00, 0x00, 0x00,
2387 0x00, 0x00, 0x00, 0x00, // Stream id
2388 0x00, 0x00, 0x00, 0x00, // Status
2389 0x47, 0x41, // Opaque Description
2391 SpdyGoAwayIR
goaway_ir(0, GOAWAY_OK
, "GA");
2392 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2394 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2395 } else if (IsSpdy3()) {
2396 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2398 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2403 const char kDescription
[] = "GOAWAY frame with max stream ID, status";
2404 const unsigned char kV2FrameData
[] = {
2405 0x80, spdy_version_ch_
, 0x00, 0x07,
2406 0x00, 0x00, 0x00, 0x04,
2407 0x7f, 0xff, 0xff, 0xff, // Stream Id
2409 const unsigned char kV3FrameData
[] = {
2410 0x80, spdy_version_ch_
, 0x00, 0x07,
2411 0x00, 0x00, 0x00, 0x08,
2412 0x7f, 0xff, 0xff, 0xff, // Stream Id
2413 0x00, 0x00, 0x00, 0x02, // Status
2415 const unsigned char kV4FrameData
[] = {
2416 0x00, 0x12, 0x07, 0x00,
2417 0x00, 0x00, 0x00, 0x00,
2418 0x7f, 0xff, 0xff, 0xff, // Stream Id
2419 0x00, 0x00, 0x00, 0x02, // Status
2420 0x47, 0x41, // Opaque Description
2422 SpdyGoAwayIR
goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR
, "GA");
2423 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2425 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2426 } else if (IsSpdy3()) {
2427 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2429 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2434 TEST_P(SpdyFramerTest
, CreateHeadersUncompressed
) {
2435 SpdyFramer
framer(spdy_version_
);
2436 framer
.set_enable_compression(false);
2439 const char kDescription
[] = "HEADERS frame, no FIN";
2441 const unsigned char kV2FrameData
[] = {
2442 0x80, spdy_version_ch_
, 0x00, 0x08,
2443 0x00, 0x00, 0x00, 0x1C,
2444 0x00, 0x00, 0x00, 0x01,
2445 0x00, 0x00, 0x00, 0x02,
2446 0x00, 0x03, 'b', 'a',
2447 'r', 0x00, 0x03, 'f',
2448 'o', 'o', 0x00, 0x03,
2449 'f', 'o', 'o', 0x00,
2452 const unsigned char kV3FrameData
[] = {
2453 0x80, spdy_version_ch_
, 0x00, 0x08,
2454 0x00, 0x00, 0x00, 0x24,
2455 0x00, 0x00, 0x00, 0x01,
2456 0x00, 0x00, 0x00, 0x02,
2457 0x00, 0x00, 0x00, 0x03,
2458 'b', 'a', 'r', 0x00,
2459 0x00, 0x00, 0x03, 'f',
2460 'o', 'o', 0x00, 0x00,
2461 0x00, 0x03, 'f', 'o',
2462 'o', 0x00, 0x00, 0x00,
2465 const unsigned char kV4FrameData
[] = {
2466 0x00, 0x1a, 0x08, 0x04, // Headers: END_HEADERS
2467 0x00, 0x00, 0x00, 0x01, // Stream 1
2468 0x40, 0x03, 0x62, 0x61, // @.ba
2469 0x72, 0x03, 0x66, 0x6f, // r.fo
2470 0x6f, 0x40, 0x03, 0x66, // o@.f
2471 0x6f, 0x6f, 0x03, 0x62, // oo.b
2474 SpdyHeadersIR
headers_ir(1);
2475 headers_ir
.SetHeader("bar", "foo");
2476 headers_ir
.SetHeader("foo", "bar");
2477 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2479 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2480 } else if (IsSpdy3()) {
2481 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2483 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2488 const char kDescription
[] =
2489 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2491 const unsigned char kV2FrameData
[] = {
2492 0x80, spdy_version_ch_
, 0x00, 0x08,
2493 0x01, 0x00, 0x00, 0x19,
2494 0x7f, 0xff, 0xff, 0xff,
2495 0x00, 0x00, 0x00, 0x02,
2496 0x00, 0x00, 0x00, 0x03,
2497 'f', 'o', 'o', 0x00,
2498 0x03, 'f', 'o', 'o',
2499 0x00, 0x03, 'b', 'a',
2502 const unsigned char kV3FrameData
[] = {
2503 0x80, spdy_version_ch_
, 0x00, 0x08,
2504 0x01, 0x00, 0x00, 0x21,
2505 0x7f, 0xff, 0xff, 0xff,
2506 0x00, 0x00, 0x00, 0x02,
2507 0x00, 0x00, 0x00, 0x00,
2508 0x00, 0x00, 0x00, 0x03,
2509 'f', 'o', 'o', 0x00,
2510 0x00, 0x00, 0x03, 'f',
2511 'o', 'o', 0x00, 0x00,
2512 0x00, 0x03, 'b', 'a',
2515 const unsigned char kV4FrameData
[] = {
2516 0x00, 0x17, 0x08, 0x05, // HEADER: FIN | END_HEADERS
2517 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2518 0x40, 0x00, 0x03, 0x66, // @..f
2519 0x6f, 0x6f, 0x40, 0x03, // oo@.
2520 0x66, 0x6f, 0x6f, 0x03, // foo.
2521 0x62, 0x61, 0x72, // bar
2523 SpdyHeadersIR
headers_ir(0x7fffffff);
2524 headers_ir
.set_fin(true);
2525 headers_ir
.SetHeader("", "foo");
2526 headers_ir
.SetHeader("foo", "bar");
2527 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2529 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2530 } else if (IsSpdy3()) {
2531 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2533 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2538 const char kDescription
[] =
2539 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2541 const unsigned char kV2FrameData
[] = {
2542 0x80, spdy_version_ch_
, 0x00, 0x08,
2543 0x01, 0x00, 0x00, 0x19,
2544 0x7f, 0xff, 0xff, 0xff,
2545 0x00, 0x00, 0x00, 0x02,
2546 0x00, 0x03, 'b', 'a',
2547 'r', 0x00, 0x03, 'f',
2548 'o', 'o', 0x00, 0x03,
2549 'f', 'o', 'o', 0x00,
2552 const unsigned char kV3FrameData
[] = {
2553 0x80, spdy_version_ch_
, 0x00, 0x08,
2554 0x01, 0x00, 0x00, 0x21,
2555 0x7f, 0xff, 0xff, 0xff,
2556 0x00, 0x00, 0x00, 0x02,
2557 0x00, 0x00, 0x00, 0x03,
2558 'b', 'a', 'r', 0x00,
2559 0x00, 0x00, 0x03, 'f',
2560 'o', 'o', 0x00, 0x00,
2561 0x00, 0x03, 'f', 'o',
2562 'o', 0x00, 0x00, 0x00,
2565 const unsigned char kV4FrameData
[] = {
2566 0x00, 0x17, 0x08, 0x05, // HEADER: FIN | END_HEADERS
2567 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2568 0x40, 0x03, 0x62, 0x61, // @.ba
2569 0x72, 0x03, 0x66, 0x6f, // r.fo
2570 0x6f, 0x40, 0x03, 0x66, // o@.f
2571 0x6f, 0x6f, 0x00, // oo.
2573 SpdyHeadersIR
headers_ir(0x7fffffff);
2574 headers_ir
.set_fin(true);
2575 headers_ir
.SetHeader("bar", "foo");
2576 headers_ir
.SetHeader("foo", "");
2577 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2579 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2580 } else if (IsSpdy3()) {
2581 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2583 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2588 // TODO(phajdan.jr): Clean up after we no longer need
2589 // to workaround http://crbug.com/139744.
2590 #if !defined(USE_SYSTEM_ZLIB)
2591 TEST_P(SpdyFramerTest
, CreateHeadersCompressed
) {
2592 SpdyFramer
framer(spdy_version_
);
2593 framer
.set_enable_compression(true);
2596 const char kDescription
[] = "HEADERS frame, no FIN";
2598 const unsigned char kV2FrameData
[] = {
2599 0x80, spdy_version_ch_
, 0x00, 0x08,
2600 0x00, 0x00, 0x00, 0x32,
2601 0x00, 0x00, 0x00, 0x01,
2602 0x00, 0x00, 0x38, 0xea,
2603 0xdf, 0xa2, 0x51, 0xb2,
2604 0x62, 0x60, 0x62, 0x60,
2605 0x4e, 0x4a, 0x2c, 0x62,
2606 0x60, 0x06, 0x08, 0xa0,
2607 0xb4, 0xfc, 0x7c, 0x80,
2608 0x00, 0x62, 0x60, 0x4e,
2609 0xcb, 0xcf, 0x67, 0x60,
2610 0x06, 0x08, 0xa0, 0xa4,
2611 0xc4, 0x22, 0x80, 0x00,
2612 0x02, 0x00, 0x00, 0x00,
2615 const unsigned char kV3FrameData
[] = {
2616 0x80, spdy_version_ch_
, 0x00, 0x08,
2617 0x00, 0x00, 0x00, 0x31,
2618 0x00, 0x00, 0x00, 0x01,
2619 0x38, 0xea, 0xe3, 0xc6,
2620 0xa7, 0xc2, 0x02, 0xe5,
2621 0x0e, 0x50, 0xc2, 0x4b,
2622 0x4a, 0x04, 0xe5, 0x0b,
2623 0x66, 0x80, 0x00, 0x4a,
2624 0xcb, 0xcf, 0x07, 0x08,
2625 0x20, 0x10, 0x95, 0x96,
2626 0x9f, 0x0f, 0xa2, 0x00,
2627 0x02, 0x28, 0x29, 0xb1,
2628 0x08, 0x20, 0x80, 0x00,
2629 0x00, 0x00, 0x00, 0xff,
2632 SpdyHeadersIR
headers_ir(1);
2633 headers_ir
.SetHeader("bar", "foo");
2634 headers_ir
.SetHeader("foo", "bar");
2635 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2637 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2638 } else if (IsSpdy3()) {
2639 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2641 // Deflate compression doesn't apply to HPACK.
2645 #endif // !defined(USE_SYSTEM_ZLIB)
2647 TEST_P(SpdyFramerTest
, CreateWindowUpdate
) {
2648 SpdyFramer
framer(spdy_version_
);
2651 const char kDescription
[] = "WINDOW_UPDATE frame";
2652 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2653 0x80, spdy_version_ch_
, 0x00, 0x09,
2654 0x00, 0x00, 0x00, 0x08,
2655 0x00, 0x00, 0x00, 0x01,
2656 0x00, 0x00, 0x00, 0x01,
2658 const unsigned char kV4FrameData
[] = {
2659 0x00, 0x0c, 0x09, 0x00,
2660 0x00, 0x00, 0x00, 0x01,
2661 0x00, 0x00, 0x00, 0x01,
2663 scoped_ptr
<SpdyFrame
> frame(
2664 framer
.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 1)));
2666 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2668 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2673 const char kDescription
[] = "WINDOW_UPDATE frame with max stream ID";
2674 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2675 0x80, spdy_version_ch_
, 0x00, 0x09,
2676 0x00, 0x00, 0x00, 0x08,
2677 0x7f, 0xff, 0xff, 0xff,
2678 0x00, 0x00, 0x00, 0x01,
2680 const unsigned char kV4FrameData
[] = {
2681 0x00, 0x0c, 0x09, 0x00,
2682 0x7f, 0xff, 0xff, 0xff,
2683 0x00, 0x00, 0x00, 0x01,
2685 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
2686 net::SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2688 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2690 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2695 const char kDescription
[] = "WINDOW_UPDATE frame with max window delta";
2696 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2697 0x80, spdy_version_ch_
, 0x00, 0x09,
2698 0x00, 0x00, 0x00, 0x08,
2699 0x00, 0x00, 0x00, 0x01,
2700 0x7f, 0xff, 0xff, 0xff,
2702 const unsigned char kV4FrameData
[] = {
2703 0x00, 0x0c, 0x09, 0x00,
2704 0x00, 0x00, 0x00, 0x01,
2705 0x7f, 0xff, 0xff, 0xff,
2707 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
2708 net::SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2710 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2712 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2717 TEST_P(SpdyFramerTest
, SerializeBlocked
) {
2718 if (spdy_version_
< SPDY4
) {
2722 SpdyFramer
framer(spdy_version_
);
2724 const char kDescription
[] = "BLOCKED frame";
2725 const unsigned char kFrameData
[] = {
2726 0x00, 0x08, 0x0b, 0x00,
2727 0x00, 0x00, 0x00, 0x00,
2729 SpdyBlockedIR
blocked_ir(0);
2730 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
2731 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
2734 TEST_P(SpdyFramerTest
, CreateBlocked
) {
2735 if (spdy_version_
< SPDY4
) {
2739 SpdyFramer
framer(spdy_version_
);
2741 const char kDescription
[] = "BLOCKED frame";
2742 const SpdyStreamId kStreamId
= 3;
2744 scoped_ptr
<SpdySerializedFrame
> frame_serialized(
2745 framer
.SerializeBlocked(SpdyBlockedIR(kStreamId
)));
2746 SpdyBlockedIR
blocked_ir(kStreamId
);
2747 scoped_ptr
<SpdySerializedFrame
> frame_created(
2748 framer
.SerializeFrame(blocked_ir
));
2750 CompareFrames(kDescription
, *frame_serialized
, *frame_created
);
2753 TEST_P(SpdyFramerTest
, CreatePushPromise
) {
2754 if (spdy_version_
< SPDY4
) {
2758 SpdyFramer
framer(spdy_version_
);
2760 const char kDescription
[] = "PUSH_PROMISE frame";
2762 const unsigned char kFrameData
[] = {
2763 0x00, 0x1e, 0x0c, 0x04, // PUSH_PROMISE: END_HEADERS
2764 0x00, 0x00, 0x00, 0x2a, // Stream 42
2765 0x00, 0x00, 0x00, 0x39, // Promised stream 57
2766 0x40, 0x03, 0x62, 0x61, // @.ba
2767 0x72, 0x03, 0x66, 0x6f, // r.fo
2768 0x6f, 0x40, 0x03, 0x66, // o@.f
2769 0x6f, 0x6f, 0x03, 0x62, // oo.b
2773 SpdyPushPromiseIR
push_promise(42, 57);
2774 push_promise
.SetHeader("bar", "foo");
2775 push_promise
.SetHeader("foo", "bar");
2776 scoped_ptr
<SpdySerializedFrame
> frame(
2777 framer
.SerializePushPromise(push_promise
));
2778 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
2781 TEST_P(SpdyFramerTest
, ReadCompressedSynStreamHeaderBlock
) {
2782 SpdyFramer
framer(spdy_version_
);
2783 SpdySynStreamIR
syn_stream(1);
2784 syn_stream
.set_priority(1);
2785 syn_stream
.SetHeader("aa", "vv");
2786 syn_stream
.SetHeader("bb", "ww");
2787 SpdyHeaderBlock headers
= syn_stream
.name_value_block();
2788 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
2789 EXPECT_TRUE(control_frame
.get() != NULL
);
2790 TestSpdyVisitor
visitor(spdy_version_
);
2791 visitor
.use_compression_
= true;
2792 visitor
.SimulateInFramer(
2793 reinterpret_cast<unsigned char*>(control_frame
->data()),
2794 control_frame
->size());
2795 EXPECT_EQ(1, visitor
.syn_frame_count_
);
2796 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
2799 TEST_P(SpdyFramerTest
, ReadCompressedSynReplyHeaderBlock
) {
2800 SpdyFramer
framer(spdy_version_
);
2801 SpdySynReplyIR
syn_reply(1);
2802 syn_reply
.SetHeader("alpha", "beta");
2803 syn_reply
.SetHeader("gamma", "delta");
2804 SpdyHeaderBlock headers
= syn_reply
.name_value_block();
2805 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynReply(syn_reply
));
2806 EXPECT_TRUE(control_frame
.get() != NULL
);
2807 TestSpdyVisitor
visitor(spdy_version_
);
2808 visitor
.use_compression_
= true;
2809 visitor
.SimulateInFramer(
2810 reinterpret_cast<unsigned char*>(control_frame
->data()),
2811 control_frame
->size());
2813 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
2814 EXPECT_EQ(1, visitor
.headers_frame_count_
);
2816 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
2817 EXPECT_EQ(0, visitor
.headers_frame_count_
);
2819 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
2822 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlock
) {
2823 SpdyFramer
framer(spdy_version_
);
2824 SpdyHeadersIR
headers_ir(1);
2825 headers_ir
.SetHeader("alpha", "beta");
2826 headers_ir
.SetHeader("gamma", "delta");
2827 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
2828 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
2829 EXPECT_TRUE(control_frame
.get() != NULL
);
2830 TestSpdyVisitor
visitor(spdy_version_
);
2831 visitor
.use_compression_
= true;
2832 visitor
.SimulateInFramer(
2833 reinterpret_cast<unsigned char*>(control_frame
->data()),
2834 control_frame
->size());
2835 EXPECT_EQ(1, visitor
.headers_frame_count_
);
2836 // control_frame_header_data_count_ depends on the random sequence
2837 // produced by rand(), so adding, removing or running single tests
2838 // alters this value. The best we can do is assert that it happens
2840 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
2841 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
2842 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
2843 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
2846 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlockWithHalfClose
) {
2847 SpdyFramer
framer(spdy_version_
);
2848 SpdyHeadersIR
headers_ir(1);
2849 headers_ir
.set_fin(true);
2850 headers_ir
.SetHeader("alpha", "beta");
2851 headers_ir
.SetHeader("gamma", "delta");
2852 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
2853 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
2854 EXPECT_TRUE(control_frame
.get() != NULL
);
2855 TestSpdyVisitor
visitor(spdy_version_
);
2856 visitor
.use_compression_
= true;
2857 visitor
.SimulateInFramer(
2858 reinterpret_cast<unsigned char*>(control_frame
->data()),
2859 control_frame
->size());
2860 EXPECT_EQ(1, visitor
.headers_frame_count_
);
2861 // control_frame_header_data_count_ depends on the random sequence
2862 // produced by rand(), so adding, removing or running single tests
2863 // alters this value. The best we can do is assert that it happens
2865 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
2866 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
2867 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
2868 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
2871 TEST_P(SpdyFramerTest
, ControlFrameAtMaxSizeLimit
) {
2872 if (spdy_version_
>= 4) {
2873 // TODO(jgraettinger): This test setup doesn't work with HPACK.
2876 // First find the size of the header value in order to just reach the control
2878 SpdyFramer
framer(spdy_version_
);
2879 framer
.set_enable_compression(false);
2880 SpdySynStreamIR
syn_stream(1);
2881 syn_stream
.set_priority(1);
2882 syn_stream
.SetHeader("aa", "");
2883 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
2884 const size_t kBigValueSize
=
2885 framer
.GetControlFrameBufferMaxSize() - control_frame
->size();
2887 // Create a frame at exactly that size.
2888 string
big_value(kBigValueSize
, 'x');
2889 syn_stream
.SetHeader("aa", big_value
.c_str());
2890 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
2891 EXPECT_TRUE(control_frame
.get() != NULL
);
2892 EXPECT_EQ(framer
.GetControlFrameBufferMaxSize(), control_frame
->size());
2894 TestSpdyVisitor
visitor(spdy_version_
);
2895 visitor
.SimulateInFramer(
2896 reinterpret_cast<unsigned char*>(control_frame
->data()),
2897 control_frame
->size());
2898 EXPECT_TRUE(visitor
.header_buffer_valid_
);
2899 EXPECT_EQ(0, visitor
.error_count_
);
2900 EXPECT_EQ(1, visitor
.syn_frame_count_
);
2901 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
2902 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
2903 EXPECT_LT(kBigValueSize
, visitor
.header_buffer_length_
);
2906 TEST_P(SpdyFramerTest
, ControlFrameTooLarge
) {
2907 if (spdy_version_
>= 4) {
2908 // TODO(jgraettinger): This test setup doesn't work with HPACK.
2911 // First find the size of the header value in order to just reach the control
2913 SpdyFramer
framer(spdy_version_
);
2914 framer
.set_enable_compression(false);
2915 SpdySynStreamIR
syn_stream(1);
2916 syn_stream
.SetHeader("aa", "");
2917 syn_stream
.set_priority(1);
2918 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
2919 const size_t kBigValueSize
=
2920 framer
.GetControlFrameBufferMaxSize() - control_frame
->size() + 1;
2922 // Create a frame at exatly that size.
2923 string
big_value(kBigValueSize
, 'x');
2924 syn_stream
.SetHeader("aa", big_value
.c_str());
2925 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
2926 // neither support that in Chromium, nor do we use the same DFATAL (see
2927 // SpdyFrameBuilder::WriteFramePrefix()).
2928 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
2930 EXPECT_TRUE(control_frame
.get() != NULL
);
2931 EXPECT_EQ(framer
.GetControlFrameBufferMaxSize() + 1,
2932 control_frame
->size());
2934 TestSpdyVisitor
visitor(spdy_version_
);
2935 visitor
.SimulateInFramer(
2936 reinterpret_cast<unsigned char*>(control_frame
->data()),
2937 control_frame
->size());
2938 EXPECT_FALSE(visitor
.header_buffer_valid_
);
2939 EXPECT_EQ(1, visitor
.error_count_
);
2940 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
2941 visitor
.framer_
.error_code())
2942 << SpdyFramer::ErrorCodeToString(framer
.error_code());
2943 EXPECT_EQ(0, visitor
.syn_frame_count_
);
2944 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
2947 // Check that the framer stops delivering header data chunks once the visitor
2948 // declares it doesn't want any more. This is important to guard against
2949 // "zip bomb" types of attacks.
2950 TEST_P(SpdyFramerTest
, ControlFrameMuchTooLarge
) {
2951 const size_t kHeaderBufferChunks
= 4;
2952 const size_t kHeaderBufferSize
=
2953 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks
;
2954 const size_t kBigValueSize
= kHeaderBufferSize
* 2;
2955 string
big_value(kBigValueSize
, 'x');
2956 SpdyFramer
framer(spdy_version_
);
2957 SpdySynStreamIR
syn_stream(1);
2958 syn_stream
.set_priority(1);
2959 syn_stream
.set_fin(true);
2960 syn_stream
.SetHeader("aa", big_value
.c_str());
2961 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
2962 EXPECT_TRUE(control_frame
.get() != NULL
);
2963 TestSpdyVisitor
visitor(spdy_version_
);
2964 visitor
.set_header_buffer_size(kHeaderBufferSize
);
2965 visitor
.use_compression_
= true;
2966 visitor
.SimulateInFramer(
2967 reinterpret_cast<unsigned char*>(control_frame
->data()),
2968 control_frame
->size());
2969 EXPECT_FALSE(visitor
.header_buffer_valid_
);
2970 EXPECT_EQ(1, visitor
.error_count_
);
2971 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
2972 visitor
.framer_
.error_code())
2973 << SpdyFramer::ErrorCodeToString(framer
.error_code());
2975 // The framer should have stoped delivering chunks after the visitor
2976 // signaled "stop" by returning false from OnControlFrameHeaderData().
2978 // control_frame_header_data_count_ depends on the random sequence
2979 // produced by rand(), so adding, removing or running single tests
2980 // alters this value. The best we can do is assert that it happens
2981 // at least kHeaderBufferChunks + 1.
2982 EXPECT_LE(kHeaderBufferChunks
+ 1,
2983 static_cast<unsigned>(visitor
.control_frame_header_data_count_
));
2984 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
2986 // The framer should not have sent half-close to the visitor.
2987 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
2990 TEST_P(SpdyFramerTest
, DecompressCorruptHeaderBlock
) {
2991 if (spdy_version_
>= 4) {
2992 // Deflate compression doesn't apply to HPACK.
2995 SpdyFramer
framer(spdy_version_
);
2996 framer
.set_enable_compression(false);
2997 // Construct a SYN_STREAM control frame without compressing the header block,
2998 // and have the framer try to decompress it. This will cause the framer to
2999 // deal with a decompression error.
3000 SpdySynStreamIR
syn_stream(1);
3001 syn_stream
.set_priority(1);
3002 syn_stream
.SetHeader("aa", "alpha beta gamma delta");
3003 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3004 TestSpdyVisitor
visitor(spdy_version_
);
3005 visitor
.use_compression_
= true;
3006 visitor
.SimulateInFramer(
3007 reinterpret_cast<unsigned char*>(control_frame
->data()),
3008 control_frame
->size());
3009 EXPECT_EQ(1, visitor
.error_count_
);
3010 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE
, visitor
.framer_
.error_code())
3011 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3012 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3015 TEST_P(SpdyFramerTest
, ControlFrameSizesAreValidated
) {
3016 SpdyFramer
framer(spdy_version_
);
3017 // Create a GoAway frame that has a few extra bytes at the end.
3018 // We create enough overhead to overflow the framer's control frame buffer.
3019 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize
);
3020 const unsigned char length
= 1 + SpdyFramer::kControlFrameBufferSize
;
3021 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3022 0x80, spdy_version_ch_
, 0x00, 0x07,
3023 0x00, 0x00, 0x00, length
,
3024 0x00, 0x00, 0x00, 0x00, // Stream ID
3025 0x00, 0x00, 0x00, 0x00, // Status
3028 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3029 // since it may carry opaque data. Verify that minimal length is tested.
3030 const unsigned char less_than_min_length
= framer
.GetGoAwayMinimumSize() - 1;
3031 const unsigned char kV4FrameData
[] = {
3032 0x00, static_cast<uint8
>(less_than_min_length
), 0x07, 0x00,
3033 0x00, 0x00, 0x00, 0x00,
3034 0x00, 0x00, 0x00, 0x00, // Stream Id
3035 0x00, 0x00, 0x00, 0x00, // Status
3037 const size_t pad_length
=
3038 length
+ framer
.GetControlFrameHeaderSize() -
3039 (IsSpdy4() ? sizeof(kV4FrameData
) : sizeof(kV3FrameData
));
3040 string
pad('A', pad_length
);
3041 TestSpdyVisitor
visitor(spdy_version_
);
3044 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3046 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3048 visitor
.SimulateInFramer(
3049 reinterpret_cast<const unsigned char*>(pad
.c_str()),
3052 EXPECT_EQ(1, visitor
.error_count_
); // This generated an error.
3053 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
3054 visitor
.framer_
.error_code())
3055 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3056 EXPECT_EQ(0, visitor
.goaway_count_
); // Frame not parsed.
3059 TEST_P(SpdyFramerTest
, ReadZeroLenSettingsFrame
) {
3060 SpdyFramer
framer(spdy_version_
);
3061 SpdySettingsIR settings_ir
;
3062 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3063 SetFrameLength(control_frame
.get(), 0, spdy_version_
);
3064 TestSpdyVisitor
visitor(spdy_version_
);
3065 visitor
.use_compression_
= false;
3066 visitor
.SimulateInFramer(
3067 reinterpret_cast<unsigned char*>(control_frame
->data()),
3068 framer
.GetControlFrameHeaderSize());
3069 // Should generate an error, since zero-len settings frames are unsupported.
3070 EXPECT_EQ(1, visitor
.error_count_
);
3073 // Tests handling of SETTINGS frames with invalid length.
3074 TEST_P(SpdyFramerTest
, ReadBogusLenSettingsFrame
) {
3075 SpdyFramer
framer(spdy_version_
);
3076 SpdySettingsIR settings_ir
;
3078 // Add a setting to pad the frame so that we don't get a buffer overflow when
3079 // calling SimulateInFramer() below.
3080 SettingsMap settings
;
3081 settings
[SETTINGS_UPLOAD_BANDWIDTH
] =
3082 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, 0x00000002);
3083 settings_ir
.AddSetting(SETTINGS_UPLOAD_BANDWIDTH
,
3084 true, // please persist
3087 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3088 const size_t kNewLength
= 14;
3089 SetFrameLength(control_frame
.get(), kNewLength
, spdy_version_
);
3090 TestSpdyVisitor
visitor(spdy_version_
);
3091 visitor
.use_compression_
= false;
3092 visitor
.SimulateInFramer(
3093 reinterpret_cast<unsigned char*>(control_frame
->data()),
3094 framer
.GetControlFrameHeaderSize() + kNewLength
);
3095 // Should generate an error, since its not possible to have a
3096 // settings frame of length kNewLength.
3097 EXPECT_EQ(1, visitor
.error_count_
);
3100 // Tests handling of SETTINGS frames larger than the frame buffer size.
3101 TEST_P(SpdyFramerTest
, ReadLargeSettingsFrame
) {
3102 SpdyFramer
framer(spdy_version_
);
3103 SpdySettingsIR settings_ir
;
3104 SettingsMap settings
;
3106 SpdySettingsFlags flags
= SETTINGS_FLAG_PLEASE_PERSIST
;
3107 settings
[SETTINGS_UPLOAD_BANDWIDTH
] =
3108 SettingsFlagsAndValue(flags
, 0x00000002);
3109 settings
[SETTINGS_DOWNLOAD_BANDWIDTH
] =
3110 SettingsFlagsAndValue(flags
, 0x00000003);
3111 settings
[SETTINGS_ROUND_TRIP_TIME
] = SettingsFlagsAndValue(flags
, 0x00000004);
3112 for (SettingsMap::const_iterator it
= settings
.begin();
3113 it
!= settings
.end();
3115 settings_ir
.AddSetting(it
->first
,
3116 it
->second
.first
& SETTINGS_FLAG_PLEASE_PERSIST
,
3117 it
->second
.first
& SETTINGS_FLAG_PERSISTED
,
3121 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3122 EXPECT_LT(SpdyFramer::kControlFrameBufferSize
,
3123 control_frame
->size());
3124 TestSpdyVisitor
visitor(spdy_version_
);
3125 visitor
.use_compression_
= false;
3127 // Read all at once.
3128 visitor
.SimulateInFramer(
3129 reinterpret_cast<unsigned char*>(control_frame
->data()),
3130 control_frame
->size());
3131 EXPECT_EQ(0, visitor
.error_count_
);
3132 EXPECT_EQ(3, visitor
.setting_count_
);
3133 if (spdy_version_
>= 4) {
3134 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3137 // Read data in small chunks.
3138 size_t framed_data
= 0;
3139 size_t unframed_data
= control_frame
->size();
3140 size_t kReadChunkSize
= 5; // Read five bytes at a time.
3141 while (unframed_data
> 0) {
3142 size_t to_read
= min(kReadChunkSize
, unframed_data
);
3143 visitor
.SimulateInFramer(
3144 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
3146 unframed_data
-= to_read
;
3147 framed_data
+= to_read
;
3149 EXPECT_EQ(0, visitor
.error_count_
);
3150 EXPECT_EQ(3 * 2, visitor
.setting_count_
);
3151 if (spdy_version_
>= 4) {
3152 EXPECT_EQ(2, visitor
.settings_ack_sent_
);
3156 // Tests handling of SETTINGS frame with duplicate entries.
3157 TEST_P(SpdyFramerTest
, ReadDuplicateSettings
) {
3158 SpdyFramer
framer(spdy_version_
);
3160 const unsigned char kV2FrameData
[] = {
3161 0x80, spdy_version_ch_
, 0x00, 0x04,
3162 0x00, 0x00, 0x00, 0x1C,
3163 0x00, 0x00, 0x00, 0x03,
3164 0x01, 0x00, 0x00, 0x00, // 1st Setting
3165 0x00, 0x00, 0x00, 0x02,
3166 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3167 0x00, 0x00, 0x00, 0x03,
3168 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3169 0x00, 0x00, 0x00, 0x03,
3171 const unsigned char kV3FrameData
[] = {
3172 0x80, spdy_version_ch_
, 0x00, 0x04,
3173 0x00, 0x00, 0x00, 0x1C,
3174 0x00, 0x00, 0x00, 0x03,
3175 0x00, 0x00, 0x00, 0x01, // 1st Setting
3176 0x00, 0x00, 0x00, 0x02,
3177 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3178 0x00, 0x00, 0x00, 0x03,
3179 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3180 0x00, 0x00, 0x00, 0x03,
3182 const unsigned char kV4FrameData
[] = {
3183 0x00, 0x17, 0x04, 0x00,
3184 0x00, 0x00, 0x00, 0x00,
3185 0x01, // 1st Setting
3186 0x00, 0x00, 0x00, 0x02,
3187 0x01, // 2nd (duplicate) Setting
3188 0x00, 0x00, 0x00, 0x03,
3189 0x03, // 3rd (unprocessed) Setting
3190 0x00, 0x00, 0x00, 0x03,
3193 TestSpdyVisitor
visitor(spdy_version_
);
3194 visitor
.use_compression_
= false;
3196 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
3197 } else if (IsSpdy3()) {
3198 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3200 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3204 EXPECT_EQ(1, visitor
.setting_count_
);
3205 EXPECT_EQ(1, visitor
.error_count_
);
3207 // In SPDY 4+, duplicate settings are allowed;
3208 // each setting replaces the previous value for that setting.
3209 EXPECT_EQ(3, visitor
.setting_count_
);
3210 EXPECT_EQ(0, visitor
.error_count_
);
3211 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3215 // Tests handling of SETTINGS frame with entries out of order.
3216 TEST_P(SpdyFramerTest
, ReadOutOfOrderSettings
) {
3217 SpdyFramer
framer(spdy_version_
);
3219 const unsigned char kV2FrameData
[] = {
3220 0x80, spdy_version_ch_
, 0x00, 0x04,
3221 0x00, 0x00, 0x00, 0x1C,
3222 0x00, 0x00, 0x00, 0x03,
3223 0x02, 0x00, 0x00, 0x00, // 1st Setting
3224 0x00, 0x00, 0x00, 0x02,
3225 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
3226 0x00, 0x00, 0x00, 0x03,
3227 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3228 0x00, 0x00, 0x00, 0x03,
3230 const unsigned char kV3FrameData
[] = {
3231 0x80, spdy_version_ch_
, 0x00, 0x04,
3232 0x00, 0x00, 0x00, 0x1C,
3233 0x00, 0x00, 0x00, 0x03,
3234 0x00, 0x00, 0x00, 0x02, // 1st Setting
3235 0x00, 0x00, 0x00, 0x02,
3236 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3237 0x00, 0x00, 0x00, 0x03,
3238 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3239 0x00, 0x00, 0x00, 0x03,
3241 const unsigned char kV4FrameData
[] = {
3242 0x00, 0x17, 0x04, 0x00,
3243 0x00, 0x00, 0x00, 0x00,
3244 0x02, // 1st Setting
3245 0x00, 0x00, 0x00, 0x02,
3246 0x01, // 2nd (out of order) Setting
3247 0x00, 0x00, 0x00, 0x03,
3248 0x03, // 3rd (unprocessed) Setting
3249 0x00, 0x00, 0x00, 0x03,
3252 TestSpdyVisitor
visitor(spdy_version_
);
3253 visitor
.use_compression_
= false;
3255 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
3256 } else if (IsSpdy3()) {
3257 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3259 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3263 EXPECT_EQ(1, visitor
.setting_count_
);
3264 EXPECT_EQ(1, visitor
.error_count_
);
3266 // In SPDY 4+, settings are allowed in any order.
3267 EXPECT_EQ(3, visitor
.setting_count_
);
3268 EXPECT_EQ(0, visitor
.error_count_
);
3269 // EXPECT_EQ(1, visitor.settings_ack_count_);
3273 TEST_P(SpdyFramerTest
, ProcessSettingsAckFrame
) {
3274 if (spdy_version_
< 4) {
3277 SpdyFramer
framer(spdy_version_
);
3279 const unsigned char kFrameData
[] = {
3280 0x00, 0x08, 0x04, 0x01,
3281 0x00, 0x00, 0x00, 0x00,
3284 TestSpdyVisitor
visitor(spdy_version_
);
3285 visitor
.use_compression_
= false;
3286 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
3288 EXPECT_EQ(0, visitor
.error_count_
);
3289 EXPECT_EQ(0, visitor
.setting_count_
);
3290 EXPECT_EQ(1, visitor
.settings_ack_received_
);
3293 TEST_P(SpdyFramerTest
, ReadWindowUpdate
) {
3294 SpdyFramer
framer(spdy_version_
);
3295 scoped_ptr
<SpdyFrame
> control_frame(
3296 framer
.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 2)));
3297 TestSpdyVisitor
visitor(spdy_version_
);
3298 visitor
.SimulateInFramer(
3299 reinterpret_cast<unsigned char*>(control_frame
->data()),
3300 control_frame
->size());
3301 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
3302 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
3305 TEST_P(SpdyFramerTest
, ReceiveCredentialFrame
) {
3309 SpdyFramer
framer(spdy_version_
);
3310 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3311 0x80, spdy_version_ch_
, 0x00, 0x0A,
3312 0x00, 0x00, 0x00, 0x33,
3313 0x00, 0x03, 0x00, 0x00,
3314 0x00, 0x05, 'p', 'r',
3315 'o', 'o', 'f', 0x00,
3316 0x00, 0x00, 0x06, 'a',
3318 't', 0x00, 0x00, 0x00,
3319 0x0C, 'a', 'n', 'o',
3322 't', 0x00, 0x00, 0x00,
3323 0x0A, 'f', 'i', 'n',
3327 TestSpdyVisitor
visitor(spdy_version_
);
3328 visitor
.use_compression_
= false;
3329 visitor
.SimulateInFramer(kV3FrameData
, arraysize(kV3FrameData
));
3330 EXPECT_EQ(0, visitor
.error_count_
);
3333 TEST_P(SpdyFramerTest
, ReadCredentialFrameFollowedByAnotherFrame
) {
3337 SpdyFramer
framer(spdy_version_
);
3338 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3339 0x80, spdy_version_ch_
, 0x00, 0x0A,
3340 0x00, 0x00, 0x00, 0x33,
3341 0x00, 0x03, 0x00, 0x00,
3342 0x00, 0x05, 'p', 'r',
3343 'o', 'o', 'f', 0x00,
3344 0x00, 0x00, 0x06, 'a',
3346 't', 0x00, 0x00, 0x00,
3347 0x0C, 'a', 'n', 'o',
3350 't', 0x00, 0x00, 0x00,
3351 0x0A, 'f', 'i', 'n',
3355 TestSpdyVisitor
visitor(spdy_version_
);
3356 visitor
.use_compression_
= false;
3357 string
multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData
),
3358 arraysize(kV3FrameData
));
3359 scoped_ptr
<SpdyFrame
> control_frame(
3360 framer
.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 2)));
3361 multiple_frame_data
.append(string(control_frame
->data(),
3362 control_frame
->size()));
3363 visitor
.SimulateInFramer(
3364 reinterpret_cast<unsigned const char*>(multiple_frame_data
.data()),
3365 multiple_frame_data
.length());
3366 EXPECT_EQ(0, visitor
.error_count_
);
3367 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
3368 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
3371 TEST_P(SpdyFramerTest
, CreateContinuation
) {
3372 if (spdy_version_
< SPDY4
) {
3376 SpdyFramer
framer(spdy_version_
);
3378 const char kDescription
[] = "CONTINUATION frame";
3380 const unsigned char kFrameData
[] = {
3381 0x00, 0x1a, 0x0d, 0x00, // CONTINUATION
3382 0x00, 0x00, 0x00, 0x2a, // Stream 42
3383 0x40, 0x03, 0x62, 0x61, // @.ba
3384 0x72, 0x03, 0x66, 0x6f, // r.fo
3385 0x6f, 0x40, 0x03, 0x66, // o@.f
3386 0x6f, 0x6f, 0x03, 0x62, // oo.b
3390 SpdyContinuationIR
continuation(42);
3391 continuation
.SetHeader("bar", "foo");
3392 continuation
.SetHeader("foo", "bar");
3393 scoped_ptr
<SpdySerializedFrame
> frame(
3394 framer
.SerializeContinuation(continuation
));
3395 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3398 TEST_P(SpdyFramerTest
, ReadCompressedPushPromise
) {
3399 if (spdy_version_
< 4) {
3403 SpdyFramer
framer(spdy_version_
);
3404 SpdyPushPromiseIR
push_promise(42, 57);
3405 push_promise
.SetHeader("foo", "bar");
3406 push_promise
.SetHeader("bar", "foofoo");
3407 SpdyHeaderBlock headers
= push_promise
.name_value_block();
3408 scoped_ptr
<SpdySerializedFrame
> frame(
3409 framer
.SerializePushPromise(push_promise
));
3410 EXPECT_TRUE(frame
.get() != NULL
);
3411 TestSpdyVisitor
visitor(spdy_version_
);
3412 visitor
.use_compression_
= true;
3413 visitor
.SimulateInFramer(
3414 reinterpret_cast<unsigned char*>(frame
->data()),
3416 EXPECT_EQ(42u, visitor
.last_push_promise_stream_
);
3417 EXPECT_EQ(57u, visitor
.last_push_promise_promised_stream_
);
3418 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3421 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuation
) {
3422 if (spdy_version_
< 4) {
3426 const unsigned char kInput
[] = {
3427 0x00, 0x18, 0x08, 0x00, // HEADERS
3428 0x00, 0x00, 0x00, 0x01, // Stream 1
3429 0x40, 0x06, 0x43, 0x6f,
3430 0x6f, 0x6b, 0x69, 0x65,
3431 0x07, 0x66, 0x6f, 0x6f,
3432 0x3d, 0x62, 0x61, 0x72,
3434 0x00, 0x1c, 0x0D, 0x00, // CONTINUATION
3435 0x00, 0x00, 0x00, 0x01, // Stream 1
3436 0x40, 0x06, 0x43, 0x6f,
3437 0x6f, 0x6b, 0x69, 0x65,
3438 0x08, 0x62, 0x61, 0x7a,
3439 0x3d, 0x62, 0x69, 0x6e,
3440 0x67, 0x40, 0x06, 0x43,
3442 0x00, 0x1a, 0x0D, 0x04, // CONTINUATION: END_HEADERS
3443 0x00, 0x00, 0x00, 0x01, // Stream 1
3444 0x6f, 0x6f, 0x6b, 0x69,
3445 0x65, 0x00, 0x40, 0x04,
3446 0x6e, 0x61, 0x6d, 0x65,
3447 0x05, 0x76, 0x61, 0x6c,
3451 SpdyFramer
framer(spdy_version_
);
3452 TestSpdyVisitor
visitor(spdy_version_
);
3453 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3455 EXPECT_EQ(0, visitor
.error_count_
);
3456 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3457 EXPECT_EQ(2, visitor
.continuation_count_
);
3458 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3459 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3461 EXPECT_THAT(visitor
.headers_
, ElementsAre(
3462 Pair("Cookie", "foo=bar; baz=bing; "),
3463 Pair("name", "value")));
3466 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuationAndFin
) {
3467 if (spdy_version_
< 4) {
3471 const unsigned char kInput
[] = {
3472 0x00, 0x18, 0x08, 0x01, // HEADERS: FIN
3473 0x00, 0x00, 0x00, 0x01, // Stream 1
3474 0x40, 0x06, 0x43, 0x6f,
3475 0x6f, 0x6b, 0x69, 0x65,
3476 0x07, 0x66, 0x6f, 0x6f,
3477 0x3d, 0x62, 0x61, 0x72,
3479 0x00, 0x1c, 0x0D, 0x00, // CONTINUATION
3480 0x00, 0x00, 0x00, 0x01, // Stream 1
3481 0x40, 0x06, 0x43, 0x6f,
3482 0x6f, 0x6b, 0x69, 0x65,
3483 0x08, 0x62, 0x61, 0x7a,
3484 0x3d, 0x62, 0x69, 0x6e,
3485 0x67, 0x40, 0x06, 0x43,
3487 0x00, 0x1a, 0x0D, 0x04, // CONTINUATION: END_HEADERS
3488 0x00, 0x00, 0x00, 0x01, // Stream 1
3489 0x6f, 0x6f, 0x6b, 0x69,
3490 0x65, 0x00, 0x40, 0x04,
3491 0x6e, 0x61, 0x6d, 0x65,
3492 0x05, 0x76, 0x61, 0x6c,
3496 SpdyFramer
framer(spdy_version_
);
3497 TestSpdyVisitor
visitor(spdy_version_
);
3498 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3500 EXPECT_EQ(0, visitor
.error_count_
);
3501 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3502 EXPECT_EQ(2, visitor
.continuation_count_
);
3503 EXPECT_EQ(1, visitor
.fin_flag_count_
);
3504 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3505 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
3507 EXPECT_THAT(visitor
.headers_
, ElementsAre(
3508 Pair("Cookie", "foo=bar; baz=bing; "),
3509 Pair("name", "value")));
3512 TEST_P(SpdyFramerTest
, ReadPushPromiseWithContinuation
) {
3513 if (spdy_version_
< 4) {
3517 const unsigned char kInput
[] = {
3518 0x00, 0x1c, 0x0C, 0x00, // PUSH_PROMISE
3519 0x00, 0x00, 0x00, 0x01, // Stream 1
3520 0x00, 0x00, 0x00, 0x2A, // Promised stream 42
3521 0x40, 0x06, 0x43, 0x6f,
3522 0x6f, 0x6b, 0x69, 0x65,
3523 0x07, 0x66, 0x6f, 0x6f,
3524 0x3d, 0x62, 0x61, 0x72,
3526 0x00, 0x1c, 0x0D, 0x00, // CONTINUATION
3527 0x00, 0x00, 0x00, 0x01, // Stream 1
3528 0x40, 0x06, 0x43, 0x6f,
3529 0x6f, 0x6b, 0x69, 0x65,
3530 0x08, 0x62, 0x61, 0x7a,
3531 0x3d, 0x62, 0x69, 0x6e,
3532 0x67, 0x40, 0x06, 0x43,
3534 0x00, 0x1a, 0x0D, 0x04, // CONTINUATION: END_HEADERS
3535 0x00, 0x00, 0x00, 0x01, // Stream 1
3536 0x6f, 0x6f, 0x6b, 0x69,
3537 0x65, 0x00, 0x40, 0x04,
3538 0x6e, 0x61, 0x6d, 0x65,
3539 0x05, 0x76, 0x61, 0x6c,
3543 SpdyFramer
framer(spdy_version_
);
3544 TestSpdyVisitor
visitor(spdy_version_
);
3545 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3547 EXPECT_EQ(0, visitor
.error_count_
);
3548 EXPECT_EQ(1u, visitor
.last_push_promise_stream_
);
3549 EXPECT_EQ(42u, visitor
.last_push_promise_promised_stream_
);
3550 EXPECT_EQ(2, visitor
.continuation_count_
);
3551 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3552 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3554 EXPECT_THAT(visitor
.headers_
, ElementsAre(
3555 Pair("Cookie", "foo=bar; baz=bing; "),
3556 Pair("name", "value")));
3559 TEST_P(SpdyFramerTest
, ReadContinuationWithWrongStreamId
) {
3560 if (spdy_version_
< 4) {
3564 const unsigned char kInput
[] = {
3565 0x00, 0x18, 0x08, 0x00, // HEADERS
3566 0x00, 0x00, 0x00, 0x01, // Stream 1
3567 0x40, 0x06, 0x43, 0x6f,
3568 0x6f, 0x6b, 0x69, 0x65,
3569 0x07, 0x66, 0x6f, 0x6f,
3570 0x3d, 0x62, 0x61, 0x72,
3572 0x00, 0x1c, 0x0D, 0x00, // CONTINUATION
3573 0x00, 0x00, 0x00, 0x02, // Stream 2
3574 0x40, 0x06, 0x43, 0x6f,
3575 0x6f, 0x6b, 0x69, 0x65,
3576 0x08, 0x62, 0x61, 0x7a,
3577 0x3d, 0x62, 0x69, 0x6e,
3578 0x67, 0x40, 0x06, 0x43,
3581 SpdyFramer
framer(spdy_version_
);
3582 TestSpdyVisitor
visitor(spdy_version_
);
3583 framer
.set_visitor(&visitor
);
3584 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3586 EXPECT_EQ(1, visitor
.error_count_
);
3587 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
3588 visitor
.framer_
.error_code())
3589 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3590 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3591 EXPECT_EQ(0, visitor
.continuation_count_
);
3592 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3595 TEST_P(SpdyFramerTest
, ReadContinuationOutOfOrder
) {
3596 if (spdy_version_
< 4) {
3600 const unsigned char kInput
[] = {
3601 0x00, 0x18, 0x0D, 0x00, // CONTINUATION
3602 0x00, 0x00, 0x00, 0x01, // Stream 1
3603 0x40, 0x06, 0x43, 0x6f,
3604 0x6f, 0x6b, 0x69, 0x65,
3605 0x07, 0x66, 0x6f, 0x6f,
3606 0x3d, 0x62, 0x61, 0x72,
3609 SpdyFramer
framer(spdy_version_
);
3610 TestSpdyVisitor
visitor(spdy_version_
);
3611 framer
.set_visitor(&visitor
);
3612 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3614 EXPECT_EQ(1, visitor
.error_count_
);
3615 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
3616 visitor
.framer_
.error_code())
3617 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3618 EXPECT_EQ(0, visitor
.continuation_count_
);
3619 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3622 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveData
) {
3623 if (spdy_version_
< 4) {
3627 const unsigned char kInput
[] = {
3628 0x00, 0x18, 0x08, 0x00, // HEADERS
3629 0x00, 0x00, 0x00, 0x01, // Stream 1
3630 0x40, 0x06, 0x43, 0x6f,
3631 0x6f, 0x6b, 0x69, 0x65,
3632 0x07, 0x66, 0x6f, 0x6f,
3633 0x3d, 0x62, 0x61, 0x72,
3635 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
3636 0x00, 0x00, 0x00, 0x04,
3637 0xde, 0xad, 0xbe, 0xef,
3640 SpdyFramer
framer(spdy_version_
);
3641 TestSpdyVisitor
visitor(spdy_version_
);
3642 framer
.set_visitor(&visitor
);
3643 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3645 EXPECT_EQ(1, visitor
.error_count_
);
3646 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
3647 visitor
.framer_
.error_code())
3648 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3649 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3650 EXPECT_EQ(0, visitor
.continuation_count_
);
3651 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3652 EXPECT_EQ(0, visitor
.data_frame_count_
);
3655 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveControlFrame
) {
3656 if (spdy_version_
< 4) {
3660 const unsigned char kInput
[] = {
3661 0x00, 0x18, 0x08, 0x00, // HEADERS
3662 0x00, 0x00, 0x00, 0x01, // Stream 1
3663 0x40, 0x06, 0x43, 0x6f,
3664 0x6f, 0x6b, 0x69, 0x65,
3665 0x07, 0x66, 0x6f, 0x6f,
3666 0x3d, 0x62, 0x61, 0x72,
3668 0x00, 0x1c, 0x08, 0x00, // HEADERS
3669 0x00, 0x00, 0x00, 0x01, // Stream 1
3670 0x40, 0x06, 0x43, 0x6f, // (Note this is a valid continued encoding).
3671 0x6f, 0x6b, 0x69, 0x65,
3672 0x08, 0x62, 0x61, 0x7a,
3673 0x3d, 0x62, 0x69, 0x6e,
3674 0x67, 0x40, 0x06, 0x43,
3677 SpdyFramer
framer(spdy_version_
);
3678 TestSpdyVisitor
visitor(spdy_version_
);
3679 framer
.set_visitor(&visitor
);
3680 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
3682 EXPECT_EQ(1, visitor
.error_count_
);
3683 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
3684 visitor
.framer_
.error_code())
3685 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3686 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3687 EXPECT_EQ(0, visitor
.continuation_count_
);
3688 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3689 EXPECT_EQ(0, visitor
.data_frame_count_
);
3692 TEST_P(SpdyFramerTest
, ReadGarbage
) {
3693 SpdyFramer
framer(spdy_version_
);
3694 unsigned char garbage_frame
[256];
3695 memset(garbage_frame
, ~0, sizeof(garbage_frame
));
3696 TestSpdyVisitor
visitor(spdy_version_
);
3697 visitor
.use_compression_
= false;
3698 visitor
.SimulateInFramer(garbage_frame
, sizeof(garbage_frame
));
3699 EXPECT_EQ(1, visitor
.error_count_
);
3702 TEST_P(SpdyFramerTest
, ReadGarbageWithValidVersion
) {
3704 // Not valid for SPDY 4 since there is no version field.
3707 SpdyFramer
framer(spdy_version_
);
3708 const unsigned char kFrameData
[] = {
3709 0x80, spdy_version_ch_
, 0xff, 0xff,
3710 0xff, 0xff, 0xff, 0xff,
3712 TestSpdyVisitor
visitor(spdy_version_
);
3713 visitor
.use_compression_
= false;
3714 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
3715 EXPECT_EQ(1, visitor
.error_count_
);
3718 TEST_P(SpdyFramerTest
, SizesTest
) {
3719 SpdyFramer
framer(spdy_version_
);
3720 EXPECT_EQ(8u, framer
.GetDataFrameMinimumSize());
3722 EXPECT_EQ(8u, framer
.GetSynReplyMinimumSize());
3723 EXPECT_EQ(12u, framer
.GetRstStreamMinimumSize());
3724 EXPECT_EQ(8u, framer
.GetSettingsMinimumSize());
3725 EXPECT_EQ(16u, framer
.GetPingSize());
3726 EXPECT_EQ(16u, framer
.GetGoAwayMinimumSize());
3727 EXPECT_EQ(8u, framer
.GetHeadersMinimumSize());
3728 EXPECT_EQ(12u, framer
.GetWindowUpdateSize());
3729 EXPECT_EQ(8u, framer
.GetBlockedSize());
3730 EXPECT_EQ(12u, framer
.GetPushPromiseMinimumSize());
3731 EXPECT_EQ(8u, framer
.GetFrameMinimumSize());
3732 EXPECT_EQ(16383u, framer
.GetFrameMaximumSize());
3733 EXPECT_EQ(16375u, framer
.GetDataFrameMaximumPayload());
3735 EXPECT_EQ(8u, framer
.GetControlFrameHeaderSize());
3736 EXPECT_EQ(18u, framer
.GetSynStreamMinimumSize());
3737 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetSynReplyMinimumSize());
3738 EXPECT_EQ(16u, framer
.GetRstStreamMinimumSize());
3739 EXPECT_EQ(12u, framer
.GetSettingsMinimumSize());
3740 EXPECT_EQ(12u, framer
.GetPingSize());
3741 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer
.GetGoAwayMinimumSize());
3742 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetHeadersMinimumSize());
3743 EXPECT_EQ(16u, framer
.GetWindowUpdateSize());
3744 EXPECT_EQ(8u, framer
.GetFrameMinimumSize());
3745 EXPECT_EQ(16777223u, framer
.GetFrameMaximumSize());
3746 EXPECT_EQ(16777215u, framer
.GetDataFrameMaximumPayload());
3750 TEST_P(SpdyFramerTest
, StateToStringTest
) {
3751 EXPECT_STREQ("ERROR",
3752 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR
));
3753 EXPECT_STREQ("AUTO_RESET",
3754 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET
));
3755 EXPECT_STREQ("RESET",
3756 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET
));
3757 EXPECT_STREQ("READING_COMMON_HEADER",
3758 SpdyFramer::StateToString(
3759 SpdyFramer::SPDY_READING_COMMON_HEADER
));
3760 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
3761 SpdyFramer::StateToString(
3762 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD
));
3763 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
3764 SpdyFramer::StateToString(
3765 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD
));
3766 EXPECT_STREQ("FORWARD_STREAM_FRAME",
3767 SpdyFramer::StateToString(
3768 SpdyFramer::SPDY_FORWARD_STREAM_FRAME
));
3769 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
3770 SpdyFramer::StateToString(
3771 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
));
3772 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
3773 SpdyFramer::StateToString(
3774 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK
));
3775 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
3776 SpdyFramer::StateToString(
3777 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD
));
3778 EXPECT_STREQ("UNKNOWN_STATE",
3779 SpdyFramer::StateToString(
3780 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD
+ 1));
3783 TEST_P(SpdyFramerTest
, ErrorCodeToStringTest
) {
3784 EXPECT_STREQ("NO_ERROR",
3785 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR
));
3786 EXPECT_STREQ("INVALID_CONTROL_FRAME",
3787 SpdyFramer::ErrorCodeToString(
3788 SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
3789 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
3790 SpdyFramer::ErrorCodeToString(
3791 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
3792 EXPECT_STREQ("ZLIB_INIT_FAILURE",
3793 SpdyFramer::ErrorCodeToString(
3794 SpdyFramer::SPDY_ZLIB_INIT_FAILURE
));
3795 EXPECT_STREQ("UNSUPPORTED_VERSION",
3796 SpdyFramer::ErrorCodeToString(
3797 SpdyFramer::SPDY_UNSUPPORTED_VERSION
));
3798 EXPECT_STREQ("DECOMPRESS_FAILURE",
3799 SpdyFramer::ErrorCodeToString(
3800 SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
3801 EXPECT_STREQ("COMPRESS_FAILURE",
3802 SpdyFramer::ErrorCodeToString(
3803 SpdyFramer::SPDY_COMPRESS_FAILURE
));
3804 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
3805 SpdyFramer::ErrorCodeToString(
3806 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
3807 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
3808 SpdyFramer::ErrorCodeToString(
3809 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
));
3810 EXPECT_STREQ("UNKNOWN_ERROR",
3811 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR
));
3814 TEST_P(SpdyFramerTest
, StatusCodeToStringTest
) {
3815 EXPECT_STREQ("INVALID",
3816 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID
));
3817 EXPECT_STREQ("PROTOCOL_ERROR",
3818 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR
));
3819 EXPECT_STREQ("INVALID_STREAM",
3820 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM
));
3821 EXPECT_STREQ("REFUSED_STREAM",
3822 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM
));
3823 EXPECT_STREQ("UNSUPPORTED_VERSION",
3824 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION
));
3825 EXPECT_STREQ("CANCEL",
3826 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL
));
3827 EXPECT_STREQ("INTERNAL_ERROR",
3828 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR
));
3829 EXPECT_STREQ("FLOW_CONTROL_ERROR",
3830 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR
));
3831 EXPECT_STREQ("UNKNOWN_STATUS",
3832 SpdyFramer::StatusCodeToString(RST_STREAM_NUM_STATUS_CODES
));
3835 TEST_P(SpdyFramerTest
, FrameTypeToStringTest
) {
3836 EXPECT_STREQ("DATA",
3837 SpdyFramer::FrameTypeToString(DATA
));
3838 EXPECT_STREQ("SYN_STREAM",
3839 SpdyFramer::FrameTypeToString(SYN_STREAM
));
3840 EXPECT_STREQ("SYN_REPLY",
3841 SpdyFramer::FrameTypeToString(SYN_REPLY
));
3842 EXPECT_STREQ("RST_STREAM",
3843 SpdyFramer::FrameTypeToString(RST_STREAM
));
3844 EXPECT_STREQ("SETTINGS",
3845 SpdyFramer::FrameTypeToString(SETTINGS
));
3846 EXPECT_STREQ("NOOP",
3847 SpdyFramer::FrameTypeToString(NOOP
));
3848 EXPECT_STREQ("PING",
3849 SpdyFramer::FrameTypeToString(PING
));
3850 EXPECT_STREQ("GOAWAY",
3851 SpdyFramer::FrameTypeToString(GOAWAY
));
3852 EXPECT_STREQ("HEADERS",
3853 SpdyFramer::FrameTypeToString(HEADERS
));
3854 EXPECT_STREQ("WINDOW_UPDATE",
3855 SpdyFramer::FrameTypeToString(WINDOW_UPDATE
));
3856 EXPECT_STREQ("PUSH_PROMISE",
3857 SpdyFramer::FrameTypeToString(PUSH_PROMISE
));
3858 EXPECT_STREQ("CREDENTIAL",
3859 SpdyFramer::FrameTypeToString(CREDENTIAL
));
3860 EXPECT_STREQ("CONTINUATION",
3861 SpdyFramer::FrameTypeToString(CONTINUATION
));
3864 TEST_P(SpdyFramerTest
, CatchProbableHttpResponse
) {
3866 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
3870 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
3871 SpdyFramer
framer(spdy_version_
);
3872 framer
.set_visitor(&visitor
);
3874 EXPECT_CALL(visitor
, OnError(_
));
3875 framer
.ProcessInput("HTTP/1.1", 8);
3876 EXPECT_TRUE(framer
.probable_http_response());
3877 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
3878 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
3879 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3882 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
3883 SpdyFramer
framer(spdy_version_
);
3884 framer
.set_visitor(&visitor
);
3886 EXPECT_CALL(visitor
, OnError(_
));
3887 framer
.ProcessInput("HTTP/1.0", 8);
3888 EXPECT_TRUE(framer
.probable_http_response());
3889 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
3890 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
3891 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3895 TEST_P(SpdyFramerTest
, DataFrameFlags
) {
3896 for (int flags
= 0; flags
< 256; ++flags
) {
3897 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
3899 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
3900 SpdyFramer
framer(spdy_version_
);
3901 framer
.set_visitor(&visitor
);
3903 net::SpdyDataIR
data_ir(1, StringPiece("hello", 5));
3904 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
3905 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
3907 if (flags
& ~DATA_FLAG_FIN
) {
3908 EXPECT_CALL(visitor
, OnError(_
));
3910 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
3911 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
3912 if (flags
& DATA_FLAG_FIN
) {
3913 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
3917 framer
.ProcessInput(frame
->data(), frame
->size());
3918 if (flags
& ~DATA_FLAG_FIN
) {
3919 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
3920 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
,
3921 framer
.error_code())
3922 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3924 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
3925 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
3926 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3931 TEST_P(SpdyFramerTest
, SynStreamFrameFlags
) {
3932 for (int flags
= 0; flags
< 256; ++flags
) {
3933 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
3935 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
3936 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
3937 SpdyFramer
framer(spdy_version_
);
3938 framer
.set_visitor(&visitor
);
3939 framer
.set_debug_visitor(&debug_visitor
);
3941 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(8, SYN_STREAM
, _
, _
));
3943 SpdySynStreamIR
syn_stream(8);
3944 syn_stream
.set_associated_to_stream_id(3);
3945 syn_stream
.set_priority(1);
3946 syn_stream
.SetHeader("foo", "bar");
3947 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
3948 int set_flags
= flags
;
3950 // PRIORITY required for SYN_STREAM simulation.
3951 set_flags
|= HEADERS_FLAG_PRIORITY
;
3953 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
3956 flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
3957 EXPECT_CALL(visitor
, OnError(_
));
3958 } else if (IsSpdy4() &&
3959 flags
& ~(CONTROL_FLAG_FIN
|
3960 HEADERS_FLAG_PRIORITY
|
3961 HEADERS_FLAG_END_HEADERS
)) {
3962 EXPECT_CALL(visitor
, OnError(_
));
3964 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(8, SYN_STREAM
, _
));
3966 EXPECT_CALL(visitor
, OnSynStream(8, 0, 1, flags
& CONTROL_FLAG_FIN
,
3969 EXPECT_CALL(visitor
, OnSynStream(8, 3, 1, flags
& CONTROL_FLAG_FIN
,
3970 flags
& CONTROL_FLAG_UNIDIRECTIONAL
));
3972 EXPECT_CALL(visitor
, OnControlFrameHeaderData(8, _
, _
))
3973 .WillRepeatedly(testing::Return(true));
3974 if (flags
& DATA_FLAG_FIN
&& (!IsSpdy4() ||
3975 flags
& HEADERS_FLAG_END_HEADERS
)) {
3976 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
3978 // Do not close the stream if we are expecting a CONTINUATION frame.
3979 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
3983 framer
.ProcessInput(frame
->data(), frame
->size());
3985 flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
3986 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
3987 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
3988 framer
.error_code())
3989 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3990 } else if (IsSpdy4() &&
3991 flags
& ~(CONTROL_FLAG_FIN
|
3992 HEADERS_FLAG_PRIORITY
|
3993 HEADERS_FLAG_END_HEADERS
)) {
3994 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
3995 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
3996 framer
.error_code())
3997 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3999 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4000 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4001 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4006 TEST_P(SpdyFramerTest
, SynReplyFrameFlags
) {
4008 // Covered by HEADERS case.
4011 for (int flags
= 0; flags
< 256; ++flags
) {
4012 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4014 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4015 SpdyFramer
framer(spdy_version_
);
4016 framer
.set_visitor(&visitor
);
4018 SpdySynReplyIR
syn_reply(37);
4019 syn_reply
.SetHeader("foo", "bar");
4020 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
4021 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4023 if (flags
& ~CONTROL_FLAG_FIN
) {
4024 EXPECT_CALL(visitor
, OnError(_
));
4026 EXPECT_CALL(visitor
, OnSynReply(37, flags
& CONTROL_FLAG_FIN
));
4027 EXPECT_CALL(visitor
, OnControlFrameHeaderData(37, _
, _
))
4028 .WillRepeatedly(testing::Return(true));
4029 if (flags
& DATA_FLAG_FIN
) {
4030 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4034 framer
.ProcessInput(frame
->data(), frame
->size());
4035 if (flags
& ~CONTROL_FLAG_FIN
) {
4036 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4037 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4038 framer
.error_code())
4039 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4041 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4042 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4043 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4048 TEST_P(SpdyFramerTest
, RstStreamFrameFlags
) {
4049 for (int flags
= 0; flags
< 256; ++flags
) {
4050 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4052 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4053 SpdyFramer
framer(spdy_version_
);
4054 framer
.set_visitor(&visitor
);
4056 net::SpdyRstStreamIR
rst_stream(13, RST_STREAM_CANCEL
, "");
4057 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
4058 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4061 EXPECT_CALL(visitor
, OnError(_
));
4063 EXPECT_CALL(visitor
, OnRstStream(13, RST_STREAM_CANCEL
));
4066 framer
.ProcessInput(frame
->data(), frame
->size());
4068 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4069 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4070 framer
.error_code())
4071 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4073 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4074 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4075 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4080 TEST_P(SpdyFramerTest
, SettingsFrameFlagsOldFormat
) {
4081 if (spdy_version_
>= 4) { return; }
4082 for (int flags
= 0; flags
< 256; ++flags
) {
4083 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4085 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4086 SpdyFramer
framer(spdy_version_
);
4087 framer
.set_visitor(&visitor
);
4089 SpdySettingsIR settings_ir
;
4090 settings_ir
.AddSetting(SETTINGS_UPLOAD_BANDWIDTH
,
4094 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
4095 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4097 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
4098 EXPECT_CALL(visitor
, OnError(_
));
4100 EXPECT_CALL(visitor
, OnSettings(
4101 flags
& SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
));
4102 EXPECT_CALL(visitor
, OnSetting(SETTINGS_UPLOAD_BANDWIDTH
,
4103 SETTINGS_FLAG_NONE
, 54321));
4104 EXPECT_CALL(visitor
, OnSettingsEnd());
4107 framer
.ProcessInput(frame
->data(), frame
->size());
4108 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
4109 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4110 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4111 framer
.error_code())
4112 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4114 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4115 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4116 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4121 TEST_P(SpdyFramerTest
, SettingsFrameFlags
) {
4122 if (spdy_version_
< 4) { return; }
4123 for (int flags
= 0; flags
< 256; ++flags
) {
4124 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4126 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4127 SpdyFramer
framer(spdy_version_
);
4128 framer
.set_visitor(&visitor
);
4130 SpdySettingsIR settings_ir
;
4131 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 0, 16);
4132 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
4133 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4136 EXPECT_CALL(visitor
, OnError(_
));
4138 EXPECT_CALL(visitor
, OnSettings(flags
& SETTINGS_FLAG_ACK
));
4139 EXPECT_CALL(visitor
, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 16));
4140 EXPECT_CALL(visitor
, OnSettingsEnd());
4143 framer
.ProcessInput(frame
->data(), frame
->size());
4144 if (flags
& ~SETTINGS_FLAG_ACK
) {
4145 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4146 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4147 framer
.error_code())
4148 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4149 } else if (flags
& SETTINGS_FLAG_ACK
) {
4150 // The frame is invalid because ACK frames should have no payload.
4151 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4152 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
4153 framer
.error_code())
4154 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4156 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4157 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4158 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4163 TEST_P(SpdyFramerTest
, GoawayFrameFlags
) {
4164 for (int flags
= 0; flags
< 256; ++flags
) {
4165 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4167 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4168 SpdyFramer
framer(spdy_version_
);
4169 framer
.set_visitor(&visitor
);
4171 SpdyGoAwayIR
goaway_ir(97, GOAWAY_OK
, "test");
4172 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
4173 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4176 EXPECT_CALL(visitor
, OnError(_
));
4178 EXPECT_CALL(visitor
, OnGoAway(97, GOAWAY_OK
));
4181 framer
.ProcessInput(frame
->data(), frame
->size());
4183 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4184 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4185 framer
.error_code())
4186 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4188 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4189 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4190 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4195 TEST_P(SpdyFramerTest
, HeadersFrameFlags
) {
4196 for (int flags
= 0; flags
< 256; ++flags
) {
4197 if (IsSpdy4() && flags
& HEADERS_FLAG_PRIORITY
) {
4198 // Covered by SYN_STREAM case.
4201 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4203 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4204 SpdyFramer
framer(spdy_version_
);
4205 framer
.set_visitor(&visitor
);
4207 SpdyHeadersIR
headers_ir(57);
4208 headers_ir
.SetHeader("foo", "bar");
4209 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
4210 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4212 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
4213 EXPECT_CALL(visitor
, OnError(_
));
4214 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
4215 HEADERS_FLAG_END_HEADERS
)) {
4216 EXPECT_CALL(visitor
, OnError(_
));
4218 EXPECT_CALL(visitor
, OnHeaders(57,
4219 flags
& CONTROL_FLAG_FIN
,
4220 (flags
& HEADERS_FLAG_END_HEADERS
) ||
4222 EXPECT_CALL(visitor
, OnControlFrameHeaderData(57, _
, _
))
4223 .WillRepeatedly(testing::Return(true));
4224 if (flags
& DATA_FLAG_FIN
&& (!IsSpdy4() ||
4225 flags
& HEADERS_FLAG_END_HEADERS
)) {
4226 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4228 // Do not close the stream if we are expecting a CONTINUATION frame.
4229 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
4233 framer
.ProcessInput(frame
->data(), frame
->size());
4234 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
4235 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4236 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4237 framer
.error_code())
4238 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4239 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
| HEADERS_FLAG_PRIORITY
|
4240 HEADERS_FLAG_END_HEADERS
)) {
4241 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4242 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4243 framer
.error_code())
4244 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4245 } else if (IsSpdy4() && ~(flags
& HEADERS_FLAG_END_HEADERS
)) {
4246 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4247 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4248 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4250 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4251 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4252 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4257 TEST_P(SpdyFramerTest
, PingFrameFlags
) {
4258 for (int flags
= 0; flags
< 256; ++flags
) {
4259 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4261 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4262 SpdyFramer
framer(spdy_version_
);
4263 framer
.set_visitor(&visitor
);
4265 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePing(SpdyPingIR(42)));
4266 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4268 if (spdy_version_
>= SPDY4
&&
4269 flags
== PING_FLAG_ACK
) {
4270 EXPECT_CALL(visitor
, OnPing(42, true));
4271 } else if (flags
== 0) {
4272 EXPECT_CALL(visitor
, OnPing(42, false));
4274 EXPECT_CALL(visitor
, OnError(_
));
4277 framer
.ProcessInput(frame
->data(), frame
->size());
4278 if ((spdy_version_
>= SPDY4
&& flags
== PING_FLAG_ACK
) ||
4280 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4281 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4282 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4284 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4285 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4286 framer
.error_code())
4287 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4292 TEST_P(SpdyFramerTest
, WindowUpdateFrameFlags
) {
4293 for (int flags
= 0; flags
< 256; ++flags
) {
4294 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4296 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4297 SpdyFramer
framer(spdy_version_
);
4298 framer
.set_visitor(&visitor
);
4300 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
4301 net::SpdyWindowUpdateIR(4, 1024)));
4302 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4305 EXPECT_CALL(visitor
, OnError(_
));
4307 EXPECT_CALL(visitor
, OnWindowUpdate(4, 1024));
4310 framer
.ProcessInput(frame
->data(), frame
->size());
4312 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4313 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4314 framer
.error_code())
4315 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4317 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4318 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4319 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4324 TEST_P(SpdyFramerTest
, PushPromiseFrameFlags
) {
4325 if (spdy_version_
< SPDY4
) {
4329 for (int flags
= 0; flags
< 256; ++flags
) {
4330 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4332 testing::StrictMock
<net::test::MockSpdyFramerVisitor
> visitor
;
4333 testing::StrictMock
<net::test::MockDebugVisitor
> debug_visitor
;
4334 SpdyFramer
framer(spdy_version_
);
4335 framer
.set_visitor(&visitor
);
4336 framer
.set_debug_visitor(&debug_visitor
);
4338 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, PUSH_PROMISE
, _
, _
));
4340 SpdyPushPromiseIR
push_promise(42, 57);
4341 push_promise
.SetHeader("foo", "bar");
4342 scoped_ptr
<SpdySerializedFrame
> frame(
4343 framer
.SerializePushPromise(push_promise
));
4344 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4346 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
4347 EXPECT_CALL(visitor
, OnError(_
));
4349 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, PUSH_PROMISE
, _
));
4350 EXPECT_CALL(visitor
, OnPushPromise(42, 57,
4351 flags
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
));
4352 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
4353 .WillRepeatedly(testing::Return(true));
4356 framer
.ProcessInput(frame
->data(), frame
->size());
4357 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
4358 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4359 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4360 framer
.error_code())
4361 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4363 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4364 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4365 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4370 TEST_P(SpdyFramerTest
, ContinuationFrameFlags
) {
4371 if (spdy_version_
< SPDY4
) {
4375 for (int flags
= 0; flags
< 256; ++flags
) {
4376 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4378 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4379 testing::StrictMock
<net::test::MockDebugVisitor
> debug_visitor
;
4380 SpdyFramer
framer(spdy_version_
);
4381 framer
.set_visitor(&visitor
);
4382 framer
.set_debug_visitor(&debug_visitor
);
4384 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, HEADERS
, _
, _
));
4385 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, HEADERS
, _
));
4386 EXPECT_CALL(visitor
, OnHeaders(42, 0, false));
4387 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
4388 .WillRepeatedly(testing::Return(true));
4389 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, CONTINUATION
, _
, _
));
4391 SpdyHeadersIR
headers_ir(42);
4392 headers_ir
.SetHeader("foo", "bar");
4393 headers_ir
.set_end_headers(false);
4394 scoped_ptr
<SpdyFrame
> frame0(framer
.SerializeHeaders(headers_ir
));
4396 SpdyContinuationIR
continuation(42);
4397 continuation
.SetHeader("foo", "bar");
4398 scoped_ptr
<SpdySerializedFrame
> frame(
4399 framer
.SerializeContinuation(continuation
));
4400 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4402 if (flags
& ~(HEADERS_FLAG_END_HEADERS
)) {
4403 EXPECT_CALL(visitor
, OnError(_
));
4405 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, CONTINUATION
, _
));
4406 EXPECT_CALL(visitor
, OnContinuation(42,
4407 flags
& HEADERS_FLAG_END_HEADERS
));
4408 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
4409 .WillRepeatedly(testing::Return(true));
4412 framer
.ProcessInput(frame0
->data(), frame0
->size());
4413 framer
.ProcessInput(frame
->data(), frame
->size());
4414 if (flags
& ~(HEADERS_FLAG_END_HEADERS
)) {
4415 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4416 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
4417 framer
.error_code())
4418 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4420 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4421 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4422 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4427 TEST_P(SpdyFramerTest
, EmptySynStream
) {
4428 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4429 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
4430 SpdyFramer
framer(spdy_version_
);
4431 framer
.set_visitor(&visitor
);
4432 framer
.set_debug_visitor(&debug_visitor
);
4434 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(1, SYN_STREAM
, _
, _
));
4436 SpdySynStreamIR
syn_stream(1);
4437 syn_stream
.set_priority(1);
4438 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
4439 // Adjust size to remove the name/value block.
4443 framer
.GetSynStreamMinimumSize(),
4448 framer
.GetSynStreamMinimumSize() - framer
.GetControlFrameHeaderSize(),
4452 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(1, SYN_STREAM
, _
));
4453 EXPECT_CALL(visitor
, OnSynStream(1, 0, 1, false, false));
4454 EXPECT_CALL(visitor
, OnControlFrameHeaderData(1, NULL
, 0));
4456 framer
.ProcessInput(frame
->data(), framer
.GetSynStreamMinimumSize());
4457 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4458 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4459 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4462 TEST_P(SpdyFramerTest
, SettingsFlagsAndId
) {
4463 const uint32 kId
= 0x020304;
4464 const uint32 kFlags
= 0x01;
4465 const uint32 kWireFormat
= htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
4467 SettingsFlagsAndId id_and_flags
=
4468 SettingsFlagsAndId::FromWireFormat(spdy_version_
, kWireFormat
);
4469 EXPECT_EQ(kId
, id_and_flags
.id());
4470 EXPECT_EQ(kFlags
, id_and_flags
.flags());
4471 EXPECT_EQ(kWireFormat
, id_and_flags
.GetWireFormat(spdy_version_
));
4474 // Test handling of a RST_STREAM with out-of-bounds status codes.
4475 TEST_P(SpdyFramerTest
, RstStreamStatusBounds
) {
4476 DCHECK_GE(0xff, RST_STREAM_NUM_STATUS_CODES
);
4478 const unsigned char kV3RstStreamInvalid
[] = {
4479 0x80, spdy_version_ch_
, 0x00, 0x03,
4480 0x00, 0x00, 0x00, 0x08,
4481 0x00, 0x00, 0x00, 0x01,
4482 0x00, 0x00, 0x00, RST_STREAM_INVALID
4484 const unsigned char kV4RstStreamInvalid
[] = {
4485 0x00, 0x0c, 0x03, 0x00,
4486 0x00, 0x00, 0x00, 0x01,
4487 0x00, 0x00, 0x00, RST_STREAM_INVALID
4490 const unsigned char kV3RstStreamNumStatusCodes
[] = {
4491 0x80, spdy_version_ch_
, 0x00, 0x03,
4492 0x00, 0x00, 0x00, 0x08,
4493 0x00, 0x00, 0x00, 0x01,
4494 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES
4496 const unsigned char kV4RstStreamNumStatusCodes
[] = {
4497 0x00, 0x0c, 0x03, 0x00,
4498 0x00, 0x00, 0x00, 0x01,
4499 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES
4502 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4503 SpdyFramer
framer(spdy_version_
);
4504 framer
.set_visitor(&visitor
);
4506 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
4508 framer
.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid
),
4509 arraysize(kV4RstStreamInvalid
));
4511 framer
.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid
),
4512 arraysize(kV3RstStreamInvalid
));
4514 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4515 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4516 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4518 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
4520 framer
.ProcessInput(
4521 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes
),
4522 arraysize(kV4RstStreamNumStatusCodes
));
4524 framer
.ProcessInput(
4525 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes
),
4526 arraysize(kV3RstStreamNumStatusCodes
));
4528 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4529 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4530 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4533 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
4534 TEST_P(SpdyFramerTest
, GoAwayStreamIdBounds
) {
4535 const unsigned char kV2FrameData
[] = {
4536 0x80, spdy_version_ch_
, 0x00, 0x07,
4537 0x00, 0x00, 0x00, 0x04,
4538 0xff, 0xff, 0xff, 0xff,
4540 const unsigned char kV3FrameData
[] = {
4541 0x80, spdy_version_ch_
, 0x00, 0x07,
4542 0x00, 0x00, 0x00, 0x08,
4543 0xff, 0xff, 0xff, 0xff,
4544 0x00, 0x00, 0x00, 0x00,
4546 const unsigned char kV4FrameData
[] = {
4547 0x00, 0x10, 0x07, 0x00,
4548 0x00, 0x00, 0x00, 0x00,
4549 0xff, 0xff, 0xff, 0xff,
4550 0x00, 0x00, 0x00, 0x00,
4553 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4554 SpdyFramer
framer(spdy_version_
);
4555 framer
.set_visitor(&visitor
);
4557 EXPECT_CALL(visitor
, OnGoAway(0x7fffffff, GOAWAY_OK
));
4559 framer
.ProcessInput(reinterpret_cast<const char*>(kV2FrameData
),
4560 arraysize(kV2FrameData
));
4561 } else if (IsSpdy3()) {
4562 framer
.ProcessInput(reinterpret_cast<const char*>(kV3FrameData
),
4563 arraysize(kV3FrameData
));
4565 framer
.ProcessInput(reinterpret_cast<const char*>(kV4FrameData
),
4566 arraysize(kV4FrameData
));
4568 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4569 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4570 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4573 TEST_P(SpdyFramerTest
, OnBlocked
) {
4574 if (spdy_version_
< SPDY4
) {
4578 const SpdyStreamId kStreamId
= 0;
4580 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4581 SpdyFramer
framer(spdy_version_
);
4582 framer
.set_visitor(&visitor
);
4584 EXPECT_CALL(visitor
, OnBlocked(kStreamId
));
4586 SpdyBlockedIR
blocked_ir(0);
4587 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
4588 framer
.ProcessInput(frame
->data(), framer
.GetBlockedSize());
4590 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4591 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4592 << SpdyFramer::ErrorCodeToString(framer
.error_code());