1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
28 static const size_t kMaxDecompressedSize
= 1024;
30 class MockDebugVisitor
: public SpdyFramerDebugVisitorInterface
{
32 MOCK_METHOD4(OnSendCompressedFrame
, void(SpdyStreamId stream_id
,
37 MOCK_METHOD3(OnReceiveCompressedFrame
, void(SpdyStreamId stream_id
,
42 class SpdyFramerTestUtil
{
44 // Decompress a single frame using the decompression context held by
45 // the SpdyFramer. The implemention is meant for use only in tests
46 // and will CHECK fail if the input is anything other than a single,
47 // well-formed compressed frame.
49 // Returns a new decompressed SpdyFrame.
50 template<class SpdyFrameType
> static SpdyFrame
* DecompressFrame(
51 SpdyFramer
* framer
, const SpdyFrameType
& frame
) {
52 DecompressionVisitor
visitor(framer
->protocol_version());
53 framer
->set_visitor(&visitor
);
54 CHECK_EQ(frame
.size(), framer
->ProcessInput(frame
.data(), frame
.size()));
55 CHECK_EQ(SpdyFramer::SPDY_RESET
, framer
->state());
56 framer
->set_visitor(NULL
);
58 char* buffer
= visitor
.ReleaseBuffer();
59 CHECK(buffer
!= NULL
);
60 SpdyFrame
* decompressed_frame
= new SpdyFrame(buffer
, visitor
.size(), true);
61 SetFrameLength(decompressed_frame
,
62 visitor
.size() - framer
->GetControlFrameHeaderSize(),
63 framer
->protocol_version());
64 return decompressed_frame
;
67 class DecompressionVisitor
: public SpdyFramerVisitorInterface
{
69 explicit DecompressionVisitor(SpdyMajorVersion version
)
70 : version_(version
), size_(0), finished_(false) {}
73 CHECK(buffer_
.get() == NULL
);
76 buffer_
.reset(new char[kMaxDecompressedSize
]);
79 void OnError(SpdyFramer
* framer
) override
{ LOG(FATAL
); }
80 void OnDataFrameHeader(SpdyStreamId stream_id
,
83 LOG(FATAL
) << "Unexpected data frame header";
85 void OnStreamFrameData(SpdyStreamId stream_id
,
92 void OnStreamPadding(SpdyStreamId stream_id
, size_t len
) override
{
96 bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
97 const char* header_data
,
98 size_t len
) override
{
99 CHECK(buffer_
.get() != NULL
);
100 CHECK_GE(kMaxDecompressedSize
, size_
+ len
);
103 memcpy(buffer_
.get() + size_
, header_data
, len
);
112 void OnSynStream(SpdyStreamId stream_id
,
113 SpdyStreamId associated_stream_id
,
114 SpdyPriority priority
,
116 bool unidirectional
) override
{
117 SpdyFramer
framer(version_
);
118 framer
.set_enable_compression(false);
119 SpdySynStreamIR
syn_stream(stream_id
);
120 syn_stream
.set_associated_to_stream_id(associated_stream_id
);
121 syn_stream
.set_priority(priority
);
122 syn_stream
.set_fin(fin
);
123 syn_stream
.set_unidirectional(unidirectional
);
124 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
126 memcpy(buffer_
.get(), frame
->data(), framer
.GetSynStreamMinimumSize());
127 size_
+= framer
.GetSynStreamMinimumSize();
130 void OnSynReply(SpdyStreamId stream_id
, bool fin
) override
{
131 SpdyFramer
framer(version_
);
132 framer
.set_enable_compression(false);
133 SpdyHeadersIR
headers(stream_id
);
134 headers
.set_fin(fin
);
135 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
137 memcpy(buffer_
.get(), frame
->data(), framer
.GetHeadersMinimumSize());
138 size_
+= framer
.GetSynStreamMinimumSize();
141 void OnRstStream(SpdyStreamId stream_id
,
142 SpdyRstStreamStatus status
) override
{
145 void OnSetting(SpdySettingsIds id
, uint8 flags
, uint32 value
) override
{
148 void OnPing(SpdyPingId unique_id
, bool is_ack
) override
{ LOG(FATAL
); }
149 void OnSettingsEnd() override
{ LOG(FATAL
); }
150 void OnGoAway(SpdyStreamId last_accepted_stream_id
,
151 SpdyGoAwayStatus status
) override
{
155 void OnHeaders(SpdyStreamId stream_id
, bool has_priority
,
156 SpdyPriority priority
, bool fin
, bool end
) override
{
157 SpdyFramer
framer(version_
);
158 framer
.set_enable_compression(false);
159 SpdyHeadersIR
headers(stream_id
);
160 headers
.set_has_priority(has_priority
);
161 if (headers
.has_priority()) {
162 headers
.set_priority(priority
);
164 headers
.set_fin(fin
);
165 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
167 memcpy(buffer_
.get(), frame
->data(), framer
.GetHeadersMinimumSize());
168 size_
+= framer
.GetHeadersMinimumSize();
171 virtual void OnWindowUpdate(SpdyStreamId stream_id
, int delta_window_size
) {
175 void OnPushPromise(SpdyStreamId stream_id
,
176 SpdyStreamId promised_stream_id
,
178 SpdyFramer
framer(version_
);
179 framer
.set_enable_compression(false);
180 SpdyPushPromiseIR
push_promise(stream_id
, promised_stream_id
);
181 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePushPromise(push_promise
));
183 memcpy(buffer_
.get(), frame
->data(), framer
.GetPushPromiseMinimumSize());
184 size_
+= framer
.GetPushPromiseMinimumSize();
187 void OnContinuation(SpdyStreamId stream_id
, bool end
) override
{
191 void OnPriority(SpdyStreamId stream_id
,
192 SpdyStreamId parent_stream_id
,
194 bool exclusive
) override
{
198 bool OnUnknownFrame(SpdyStreamId stream_id
, int frame_type
) override
{
203 char* ReleaseBuffer() {
205 return buffer_
.release();
208 void OnWindowUpdate(SpdyStreamId stream_id
,
209 uint32 delta_window_size
) override
{
213 size_t size() const {
219 SpdyMajorVersion version_
;
220 scoped_ptr
<char[]> buffer_
;
224 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor
);
228 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil
);
231 class TestSpdyVisitor
: public SpdyFramerVisitorInterface
,
232 public SpdyFramerDebugVisitorInterface
{
234 // This is larger than our max frame size because header blocks that
235 // are too long can spill over into CONTINUATION frames.
236 static const size_t kDefaultHeaderBufferSize
= 16 * 1024 * 1024;
238 explicit TestSpdyVisitor(SpdyMajorVersion version
)
240 use_compression_(false),
243 syn_reply_frame_count_(0),
244 headers_frame_count_(0),
245 push_promise_frame_count_(0),
248 settings_ack_sent_(0),
249 settings_ack_received_(0),
250 continuation_count_(0),
254 on_unknown_frame_result_(false),
255 last_window_update_stream_(0),
256 last_window_update_delta_(0),
257 last_push_promise_stream_(0),
258 last_push_promise_promised_stream_(0),
263 zero_length_data_frame_count_(0),
264 control_frame_header_data_count_(0),
265 zero_length_control_frame_header_data_count_(0),
266 data_frame_count_(0),
267 last_payload_len_(0),
269 header_buffer_(new char[kDefaultHeaderBufferSize
]),
270 header_buffer_length_(0),
271 header_buffer_size_(kDefaultHeaderBufferSize
),
272 header_stream_id_(static_cast<SpdyStreamId
>(-1)),
273 header_control_type_(DATA
),
274 header_buffer_valid_(false) {}
276 void OnError(SpdyFramer
* f
) override
{
277 LOG(INFO
) << "SpdyFramer Error: "
278 << SpdyFramer::ErrorCodeToString(f
->error_code());
282 void OnDataFrameHeader(SpdyStreamId stream_id
,
286 header_stream_id_
= stream_id
;
289 void OnStreamFrameData(SpdyStreamId stream_id
,
293 EXPECT_EQ(header_stream_id_
, stream_id
);
295 ++zero_length_data_frame_count_
;
298 LOG(INFO
) << "OnStreamFrameData(" << stream_id
<< ", \"";
300 for (size_t i
= 0 ; i
< len
; ++i
) {
301 LOG(INFO
) << std::hex
<< (0xFF & static_cast<unsigned int>(data
[i
]))
305 LOG(INFO
) << "\", " << len
<< ")\n";
308 void OnStreamPadding(SpdyStreamId stream_id
, size_t len
) override
{
309 EXPECT_EQ(header_stream_id_
, stream_id
);
311 LOG(INFO
) << "OnStreamPadding(" << stream_id
<< ", " << len
<< ")\n";
314 bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
315 const char* header_data
,
316 size_t len
) override
{
317 ++control_frame_header_data_count_
;
318 CHECK_EQ(header_stream_id_
, stream_id
);
320 ++zero_length_control_frame_header_data_count_
;
321 // Indicates end-of-header-block.
323 CHECK(header_buffer_valid_
);
324 size_t parsed_length
= framer_
.ParseHeaderBlockInBuffer(
325 header_buffer_
.get(), header_buffer_length_
, &headers_
);
326 LOG_IF(DFATAL
, header_buffer_length_
!= parsed_length
)
327 << "Check failed: header_buffer_length_ == parsed_length "
328 << "(" << header_buffer_length_
<< " vs. " << parsed_length
<< ")";
331 const size_t available
= header_buffer_size_
- header_buffer_length_
;
332 if (len
> available
) {
333 header_buffer_valid_
= false;
336 memcpy(header_buffer_
.get() + header_buffer_length_
, header_data
, len
);
337 header_buffer_length_
+= len
;
341 void OnSynStream(SpdyStreamId stream_id
,
342 SpdyStreamId associated_stream_id
,
343 SpdyPriority priority
,
345 bool unidirectional
) override
{
347 if (framer_
.protocol_version() > SPDY3
) {
348 InitHeaderStreaming(HEADERS
, stream_id
);
350 InitHeaderStreaming(SYN_STREAM
, stream_id
);
357 void OnSynReply(SpdyStreamId stream_id
, bool fin
) override
{
358 ++syn_reply_frame_count_
;
359 if (framer_
.protocol_version() > SPDY3
) {
360 InitHeaderStreaming(HEADERS
, stream_id
);
362 InitHeaderStreaming(SYN_REPLY
, stream_id
);
369 void OnRstStream(SpdyStreamId stream_id
,
370 SpdyRstStreamStatus status
) override
{
374 bool OnRstStreamFrameData(const char* rst_stream_data
, size_t len
) override
{
375 if ((rst_stream_data
!= NULL
) && (len
> 0)) {
376 fin_opaque_data_
+= string(rst_stream_data
, len
);
381 void OnSetting(SpdySettingsIds id
, uint8 flags
, uint32 value
) override
{
385 void OnSettingsAck() override
{
386 DCHECK_LT(SPDY3
, framer_
.protocol_version());
387 ++settings_ack_received_
;
390 void OnSettingsEnd() override
{
391 if (framer_
.protocol_version() <= SPDY3
) { return; }
392 ++settings_ack_sent_
;
395 void OnPing(SpdyPingId unique_id
, bool is_ack
) override
{ DLOG(FATAL
); }
397 void OnGoAway(SpdyStreamId last_accepted_stream_id
,
398 SpdyGoAwayStatus status
) override
{
402 void OnHeaders(SpdyStreamId stream_id
, bool has_priority
,
403 SpdyPriority priority
, bool fin
, bool end
) override
{
404 ++headers_frame_count_
;
405 InitHeaderStreaming(HEADERS
, stream_id
);
411 void OnWindowUpdate(SpdyStreamId stream_id
,
412 uint32 delta_window_size
) override
{
413 last_window_update_stream_
= stream_id
;
414 last_window_update_delta_
= delta_window_size
;
417 void OnPushPromise(SpdyStreamId stream_id
,
418 SpdyStreamId promised_stream_id
,
420 ++push_promise_frame_count_
;
421 InitHeaderStreaming(PUSH_PROMISE
, stream_id
);
422 last_push_promise_stream_
= stream_id
;
423 last_push_promise_promised_stream_
= promised_stream_id
;
426 void OnContinuation(SpdyStreamId stream_id
, bool end
) override
{
427 ++continuation_count_
;
431 SpdyStreamId stream_id
,
433 const SpdyAltSvcWireFormat::AlternativeService
& altsvc
) override
{
434 test_altsvc_ir_
.set_stream_id(stream_id
);
435 if (origin
.length() > 0) {
436 test_altsvc_ir_
.set_origin(origin
.as_string());
438 test_altsvc_ir_
.set_protocol_id(altsvc
.protocol_id
);
439 test_altsvc_ir_
.set_host(altsvc
.host
);
440 test_altsvc_ir_
.set_port(altsvc
.port
);
441 test_altsvc_ir_
.set_max_age(altsvc
.max_age
);
442 test_altsvc_ir_
.set_p(altsvc
.p
);
446 void OnPriority(SpdyStreamId stream_id
,
447 SpdyStreamId parent_stream_id
,
449 bool exclusive
) override
{
453 bool OnUnknownFrame(SpdyStreamId stream_id
, int frame_type
) override
{
454 DLOG(INFO
) << "Unknown frame type " << frame_type
;
455 return on_unknown_frame_result_
;
458 void OnSendCompressedFrame(SpdyStreamId stream_id
,
461 size_t frame_len
) override
{
462 last_payload_len_
= payload_len
;
463 last_frame_len_
= frame_len
;
466 void OnReceiveCompressedFrame(SpdyStreamId stream_id
,
468 size_t frame_len
) override
{
469 last_frame_len_
= frame_len
;
472 // Convenience function which runs a framer simulation with particular input.
473 void SimulateInFramer(const unsigned char* input
, size_t size
) {
474 framer_
.set_enable_compression(use_compression_
);
475 framer_
.set_visitor(this);
476 size_t input_remaining
= size
;
477 const char* input_ptr
= reinterpret_cast<const char*>(input
);
478 while (input_remaining
> 0 &&
479 framer_
.error_code() == SpdyFramer::SPDY_NO_ERROR
) {
480 // To make the tests more interesting, we feed random (amd small) chunks
481 // into the framer. This simulates getting strange-sized reads from
483 const size_t kMaxReadSize
= 32;
485 (rand() % std::min(input_remaining
, kMaxReadSize
)) + 1;
486 size_t bytes_processed
= framer_
.ProcessInput(input_ptr
, bytes_read
);
487 input_remaining
-= bytes_processed
;
488 input_ptr
+= bytes_processed
;
492 void InitHeaderStreaming(SpdyFrameType header_control_type
,
493 SpdyStreamId stream_id
) {
494 if (!SpdyConstants::IsValidFrameType(framer_
.protocol_version(),
495 SpdyConstants::SerializeFrameType(framer_
.protocol_version(),
496 header_control_type
))) {
497 DLOG(FATAL
) << "Attempted to init header streaming with "
498 << "invalid control frame type: "
499 << header_control_type
;
501 memset(header_buffer_
.get(), 0, header_buffer_size_
);
502 header_buffer_length_
= 0;
503 header_stream_id_
= stream_id
;
504 header_control_type_
= header_control_type
;
505 header_buffer_valid_
= true;
506 DCHECK_NE(header_stream_id_
, SpdyFramer::kInvalidStream
);
509 // Override the default buffer size (16K). Call before using the framer!
510 void set_header_buffer_size(size_t header_buffer_size
) {
511 header_buffer_size_
= header_buffer_size
;
512 header_buffer_
.reset(new char[header_buffer_size
]);
515 // Largest control frame that the SPDY implementation sends, including the
516 // size of the header.
517 static size_t sent_control_frame_max_size() {
518 return SpdyFramer::kMaxControlFrameSize
;
521 static size_t header_data_chunk_max_size() {
522 return SpdyFramer::kHeaderDataChunkMaxSize
;
526 bool use_compression_
;
528 // Counters from the visitor callbacks.
530 int syn_frame_count_
;
531 int syn_reply_frame_count_
;
532 int headers_frame_count_
;
533 int push_promise_frame_count_
;
536 int settings_ack_sent_
;
537 int settings_ack_received_
;
538 int continuation_count_
;
541 SpdyAltSvcIR test_altsvc_ir_
;
542 bool on_unknown_frame_result_
;
543 SpdyStreamId last_window_update_stream_
;
544 uint32 last_window_update_delta_
;
545 SpdyStreamId last_push_promise_stream_
;
546 SpdyStreamId last_push_promise_promised_stream_
;
548 int fin_frame_count_
; // The count of RST_STREAM type frames received.
549 string fin_opaque_data_
;
550 int fin_flag_count_
; // The count of frames with the FIN flag set.
551 int zero_length_data_frame_count_
; // The count of zero-length data frames.
552 int control_frame_header_data_count_
; // The count of chunks received.
553 // The count of zero-length control frame header data chunks received.
554 int zero_length_control_frame_header_data_count_
;
555 int data_frame_count_
;
556 size_t last_payload_len_
;
557 size_t last_frame_len_
;
559 // Header block streaming state:
560 scoped_ptr
<char[]> header_buffer_
;
561 size_t header_buffer_length_
;
562 size_t header_buffer_size_
;
563 SpdyStreamId header_stream_id_
;
564 SpdyFrameType header_control_type_
;
565 bool header_buffer_valid_
;
566 SpdyHeaderBlock headers_
;
569 class SpdyFramerPeer
{
571 static size_t ControlFrameBufferSize() {
572 return SpdyFramer::kControlFrameBufferSize
;
574 static size_t GetNumberRequiredContinuationFrames(SpdyFramer
* framer
,
576 return framer
->GetNumberRequiredContinuationFrames(size
);
580 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
581 base::StringPiece
GetSerializedHeaders(const SpdyFrame
* frame
,
582 const SpdyFramer
& framer
) {
583 SpdyFrameReader
reader(frame
->data(), frame
->size());
584 if (framer
.protocol_version() > SPDY3
) {
585 reader
.Seek(3); // Seek past the frame length.
587 reader
.Seek(2); // Seek past the frame length.
589 SpdyFrameType frame_type
;
590 if (framer
.protocol_version() > SPDY3
) {
591 uint8 serialized_type
;
592 reader
.ReadUInt8(&serialized_type
);
593 frame_type
= SpdyConstants::ParseFrameType(framer
.protocol_version(),
595 DCHECK_EQ(HEADERS
, frame_type
);
597 reader
.ReadUInt8(&flags
);
598 if (flags
& HEADERS_FLAG_PRIORITY
) {
599 frame_type
= SYN_STREAM
;
602 uint16 serialized_type
;
603 reader
.ReadUInt16(&serialized_type
);
604 frame_type
= SpdyConstants::ParseFrameType(framer
.protocol_version(),
606 DCHECK(frame_type
== HEADERS
||
607 frame_type
== SYN_STREAM
) << frame_type
;
610 if (frame_type
== SYN_STREAM
) {
611 return StringPiece(frame
->data() + framer
.GetSynStreamMinimumSize(),
612 frame
->size() - framer
.GetSynStreamMinimumSize());
614 return StringPiece(frame
->data() + framer
.GetHeadersMinimumSize(),
615 frame
->size() - framer
.GetHeadersMinimumSize());
619 class SpdyFramerTest
: public ::testing::TestWithParam
<SpdyMajorVersion
> {
621 void SetUp() override
{
622 spdy_version_
= GetParam();
623 spdy_version_ch_
= static_cast<unsigned char>(
624 SpdyConstants::SerializeMajorVersion(spdy_version_
));
627 void CompareFrame(const string
& description
,
628 const SpdyFrame
& actual_frame
,
629 const unsigned char* expected
,
630 const int expected_len
) {
631 const unsigned char* actual
=
632 reinterpret_cast<const unsigned char*>(actual_frame
.data());
633 CompareCharArraysWithHexError(
634 description
, actual
, actual_frame
.size(), expected
, expected_len
);
637 void CompareFrames(const string
& description
,
638 const SpdyFrame
& expected_frame
,
639 const SpdyFrame
& actual_frame
) {
640 CompareCharArraysWithHexError(
642 reinterpret_cast<const unsigned char*>(expected_frame
.data()),
643 expected_frame
.size(),
644 reinterpret_cast<const unsigned char*>(actual_frame
.data()),
645 actual_frame
.size());
648 // Returns true if the two header blocks have equivalent content.
649 bool CompareHeaderBlocks(const SpdyHeaderBlock
* expected
,
650 const SpdyHeaderBlock
* actual
) {
651 if (expected
->size() != actual
->size()) {
652 LOG(ERROR
) << "Expected " << expected
->size() << " headers; actually got "
653 << actual
->size() << ".";
656 for (SpdyHeaderBlock::const_iterator it
= expected
->begin();
657 it
!= expected
->end();
659 SpdyHeaderBlock::const_iterator it2
= actual
->find(it
->first
);
660 if (it2
== actual
->end()) {
661 LOG(ERROR
) << "Expected header name '" << it
->first
<< "'.";
664 if (it
->second
.compare(it2
->second
) != 0) {
665 LOG(ERROR
) << "Expected header named '" << it
->first
666 << "' to have a value of '" << it
->second
667 << "'. The actual value received was '" << it2
->second
675 bool IsSpdy2() { return spdy_version_
== SPDY2
; }
676 bool IsSpdy3() { return spdy_version_
== SPDY3
; }
677 bool IsSpdy4() { return spdy_version_
== SPDY4
; }
679 // Version of SPDY protocol to be used.
680 SpdyMajorVersion spdy_version_
;
681 unsigned char spdy_version_ch_
;
684 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
685 INSTANTIATE_TEST_CASE_P(SpdyFramerTests
,
687 ::testing::Values(SPDY2
, SPDY3
, SPDY4
));
689 // Test that we ignore cookie where both name and value are empty.
690 TEST_P(SpdyFramerTest
, HeaderBlockWithEmptyCookie
) {
691 if (spdy_version_
> SPDY3
) {
692 // Not implemented for hpack.
696 SpdyFramer
framer(spdy_version_
);
697 framer
.set_enable_compression(true);
698 SpdyHeadersIR
headers(1);
699 headers
.set_priority(1);
700 headers
.SetHeader("cookie",
701 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
702 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
703 EXPECT_TRUE(frame
.get() != NULL
);
705 TestSpdyVisitor
visitor(spdy_version_
);
706 visitor
.use_compression_
= true;
707 visitor
.SimulateInFramer(
708 reinterpret_cast<unsigned char*>(frame
->data()),
711 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
712 EXPECT_FALSE(CompareHeaderBlocks(&headers
.name_value_block(),
714 EXPECT_EQ(1u, visitor
.headers_
.size());
715 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor
.headers_
["cookie"]);
718 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
719 TEST_P(SpdyFramerTest
, HeaderBlockInBuffer
) {
720 SpdyFramer
framer(spdy_version_
);
721 framer
.set_enable_compression(false);
723 // Encode the header block into a Headers frame.
724 SpdyHeadersIR
headers(1);
725 headers
.set_priority(1);
726 headers
.SetHeader("alpha", "beta");
727 headers
.SetHeader("gamma", "charlie");
728 headers
.SetHeader("cookie", "key1=value1; key2=value2");
729 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
730 EXPECT_TRUE(frame
.get() != NULL
);
732 TestSpdyVisitor
visitor(spdy_version_
);
733 visitor
.use_compression_
= false;
734 visitor
.SimulateInFramer(
735 reinterpret_cast<unsigned char*>(frame
->data()),
738 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
739 EXPECT_TRUE(CompareHeaderBlocks(&headers
.name_value_block(),
743 // Test that if there's not a full frame, we fail to parse it.
744 TEST_P(SpdyFramerTest
, UndersizedHeaderBlockInBuffer
) {
745 SpdyFramer
framer(spdy_version_
);
746 framer
.set_enable_compression(false);
748 // Encode the header block into a Headers frame.
749 SpdyHeadersIR
headers(1);
750 headers
.set_priority(1);
751 headers
.SetHeader("alpha", "beta");
752 headers
.SetHeader("gamma", "charlie");
753 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
754 EXPECT_TRUE(frame
.get() != NULL
);
756 TestSpdyVisitor
visitor(spdy_version_
);
757 visitor
.use_compression_
= false;
758 visitor
.SimulateInFramer(
759 reinterpret_cast<unsigned char*>(frame
->data()),
762 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
763 EXPECT_EQ(0u, visitor
.headers_
.size());
766 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
767 // (but don't crash).
768 TEST_P(SpdyFramerTest
, SynReplyWithStreamIdZero
) {
769 if (spdy_version_
> SPDY3
) {
772 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
773 SpdyFramer
framer(spdy_version_
);
774 framer
.set_visitor(&visitor
);
776 SpdySynReplyIR
syn_reply(0);
777 syn_reply
.SetHeader("alpha", "beta");
778 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeSynReply(syn_reply
));
779 ASSERT_TRUE(frame
.get() != NULL
);
781 // We shouldn't have to read the whole frame before we signal an error.
782 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
783 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
784 EXPECT_TRUE(framer
.HasError());
785 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
786 << SpdyFramer::ErrorCodeToString(framer
.error_code());
789 // Test that if we receive a HEADERS with stream ID zero, we signal an error
790 // (but don't crash).
791 TEST_P(SpdyFramerTest
, HeadersWithStreamIdZero
) {
792 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
793 SpdyFramer
framer(spdy_version_
);
794 framer
.set_visitor(&visitor
);
796 SpdyHeadersIR
headers_ir(0);
797 headers_ir
.SetHeader("alpha", "beta");
798 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeHeaders(headers_ir
));
799 ASSERT_TRUE(frame
.get() != NULL
);
801 // We shouldn't have to read the whole frame before we signal an error.
802 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
803 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
804 EXPECT_TRUE(framer
.HasError());
805 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
806 << SpdyFramer::ErrorCodeToString(framer
.error_code());
809 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
810 // error (but don't crash).
811 TEST_P(SpdyFramerTest
, PushPromiseWithStreamIdZero
) {
812 if (spdy_version_
<= SPDY3
) {
816 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
817 SpdyFramer
framer(spdy_version_
);
818 framer
.set_visitor(&visitor
);
820 SpdyPushPromiseIR
push_promise(0, 4);
821 push_promise
.SetHeader("alpha", "beta");
822 scoped_ptr
<SpdySerializedFrame
> frame(
823 framer
.SerializePushPromise(push_promise
));
824 ASSERT_TRUE(frame
.get() != NULL
);
826 // We shouldn't have to read the whole frame before we signal an error.
827 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
828 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
829 EXPECT_TRUE(framer
.HasError());
830 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
831 << SpdyFramer::ErrorCodeToString(framer
.error_code());
834 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
835 // signal an error (but don't crash).
836 TEST_P(SpdyFramerTest
, PushPromiseWithPromisedStreamIdZero
) {
837 if (spdy_version_
<= SPDY3
) {
841 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
842 SpdyFramer
framer(spdy_version_
);
843 framer
.set_visitor(&visitor
);
845 SpdyPushPromiseIR
push_promise(3, 0);
846 push_promise
.SetHeader("alpha", "beta");
847 scoped_ptr
<SpdySerializedFrame
> frame(
848 framer
.SerializePushPromise(push_promise
));
849 ASSERT_TRUE(frame
.get() != NULL
);
851 // We shouldn't have to read the whole frame before we signal an error.
852 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
853 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
854 EXPECT_TRUE(framer
.HasError());
855 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
856 << SpdyFramer::ErrorCodeToString(framer
.error_code());
859 TEST_P(SpdyFramerTest
, DuplicateHeader
) {
860 if (spdy_version_
> SPDY3
) {
861 // TODO(jgraettinger): Punting on this because we haven't determined
862 // whether duplicate HPACK headers other than Cookie are an error.
863 // If they are, this will need to be updated to use HpackOutputStream.
866 SpdyFramer
framer(spdy_version_
);
867 // Frame builder with plentiful buffer size.
868 SpdyFrameBuilder
frame(1024, spdy_version_
);
869 if (spdy_version_
<= SPDY3
) {
870 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
871 frame
.WriteUInt32(3); // stream_id
872 frame
.WriteUInt32(0); // associated stream id
873 frame
.WriteUInt16(0); // Priority.
875 frame
.BeginNewFrame(framer
, HEADERS
, HEADERS_FLAG_PRIORITY
, 3);
876 frame
.WriteUInt32(framer
.GetHighestPriority());
880 frame
.WriteUInt16(2); // Number of headers.
881 frame
.WriteStringPiece16("name");
882 frame
.WriteStringPiece16("value1");
883 frame
.WriteStringPiece16("name");
884 frame
.WriteStringPiece16("value2");
886 frame
.WriteUInt32(2); // Number of headers.
887 frame
.WriteStringPiece32("name");
888 frame
.WriteStringPiece32("value1");
889 frame
.WriteStringPiece32("name");
890 frame
.WriteStringPiece32("value2");
893 frame
.RewriteLength(framer
);
895 SpdyHeaderBlock new_headers
;
896 framer
.set_enable_compression(false);
897 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
898 base::StringPiece serialized_headers
=
899 GetSerializedHeaders(control_frame
.get(), framer
);
900 // This should fail because duplicate headers are verboten by the spec.
901 EXPECT_FALSE(framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
902 serialized_headers
.size(),
906 TEST_P(SpdyFramerTest
, MultiValueHeader
) {
907 SpdyFramer
framer(spdy_version_
);
908 // Frame builder with plentiful buffer size.
909 SpdyFrameBuilder
frame(1024, spdy_version_
);
910 if (spdy_version_
<= SPDY3
) {
911 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
912 frame
.WriteUInt32(3); // stream_id
913 frame
.WriteUInt32(0); // associated stream id
914 frame
.WriteUInt16(0); // Priority.
916 frame
.BeginNewFrame(framer
,
918 HEADERS_FLAG_PRIORITY
| HEADERS_FLAG_END_HEADERS
,
920 frame
.WriteUInt32(0); // Priority exclusivity and dependent stream.
921 frame
.WriteUInt8(255); // Priority weight.
924 string
value("value1\0value2", 13);
926 frame
.WriteUInt16(1); // Number of headers.
927 frame
.WriteStringPiece16("name");
928 frame
.WriteStringPiece16(value
);
929 } else if (spdy_version_
> SPDY3
) {
930 // TODO(jgraettinger): If this pattern appears again, move to test class.
931 std::map
<string
, string
> header_set
;
932 header_set
["name"] = value
;
934 HpackEncoder
encoder(ObtainHpackHuffmanTable());
935 encoder
.EncodeHeaderSetWithoutCompression(header_set
, &buffer
);
936 frame
.WriteBytes(&buffer
[0], buffer
.size());
938 frame
.WriteUInt32(1); // Number of headers.
939 frame
.WriteStringPiece32("name");
940 frame
.WriteStringPiece32(value
);
943 frame
.RewriteLength(framer
);
945 framer
.set_enable_compression(false);
946 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
948 TestSpdyVisitor
visitor(spdy_version_
);
949 visitor
.use_compression_
= false;
950 visitor
.SimulateInFramer(
951 reinterpret_cast<unsigned char*>(control_frame
->data()),
952 control_frame
->size());
954 EXPECT_THAT(visitor
.headers_
,
955 testing::ElementsAre(testing::Pair("name", value
)));
958 TEST_P(SpdyFramerTest
, BasicCompression
) {
959 if (spdy_version_
> SPDY3
) {
960 // Deflate compression doesn't apply to HPACK.
963 scoped_ptr
<TestSpdyVisitor
> visitor(new TestSpdyVisitor(spdy_version_
));
964 SpdyFramer
framer(spdy_version_
);
965 framer
.set_debug_visitor(visitor
.get());
966 SpdySynStreamIR
syn_stream(1);
967 syn_stream
.set_priority(1);
968 syn_stream
.SetHeader("server", "SpdyServer 1.0");
969 syn_stream
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
970 syn_stream
.SetHeader("status", "200");
971 syn_stream
.SetHeader("version", "HTTP/1.1");
972 syn_stream
.SetHeader("content-type", "text/html");
973 syn_stream
.SetHeader("content-length", "12");
974 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeSynStream(syn_stream
));
975 size_t uncompressed_size1
= visitor
->last_payload_len_
;
976 size_t compressed_size1
=
977 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
979 EXPECT_EQ(139u, uncompressed_size1
);
980 #if defined(USE_SYSTEM_ZLIB)
981 EXPECT_EQ(155u, compressed_size1
);
982 #else // !defined(USE_SYSTEM_ZLIB)
983 EXPECT_EQ(135u, compressed_size1
);
984 #endif // !defined(USE_SYSTEM_ZLIB)
986 EXPECT_EQ(165u, uncompressed_size1
);
987 #if defined(USE_SYSTEM_ZLIB)
988 EXPECT_EQ(181u, compressed_size1
);
989 #else // !defined(USE_SYSTEM_ZLIB)
990 EXPECT_EQ(117u, compressed_size1
);
991 #endif // !defined(USE_SYSTEM_ZLIB)
993 scoped_ptr
<SpdyFrame
> frame2(framer
.SerializeSynStream(syn_stream
));
994 size_t uncompressed_size2
= visitor
->last_payload_len_
;
995 size_t compressed_size2
=
996 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
998 // Expect the second frame to be more compact than the first.
999 EXPECT_LE(frame2
->size(), frame1
->size());
1001 // Decompress the first frame
1002 scoped_ptr
<SpdyFrame
> frame3(
1003 SpdyFramerTestUtil::DecompressFrame(&framer
, *frame1
));
1005 // Decompress the second frame
1006 visitor
.reset(new TestSpdyVisitor(spdy_version_
));
1007 framer
.set_debug_visitor(visitor
.get());
1008 scoped_ptr
<SpdyFrame
> frame4(
1009 SpdyFramerTestUtil::DecompressFrame(&framer
, *frame2
));
1010 size_t uncompressed_size4
=
1011 frame4
->size() - framer
.GetSynStreamMinimumSize();
1012 size_t compressed_size4
=
1013 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
1015 EXPECT_EQ(139u, uncompressed_size4
);
1016 #if defined(USE_SYSTEM_ZLIB)
1017 EXPECT_EQ(149u, compressed_size4
);
1018 #else // !defined(USE_SYSTEM_ZLIB)
1019 EXPECT_EQ(101u, compressed_size4
);
1020 #endif // !defined(USE_SYSTEM_ZLIB)
1022 EXPECT_EQ(165u, uncompressed_size4
);
1023 #if defined(USE_SYSTEM_ZLIB)
1024 EXPECT_EQ(175u, compressed_size4
);
1025 #else // !defined(USE_SYSTEM_ZLIB)
1026 EXPECT_EQ(102u, compressed_size4
);
1027 #endif // !defined(USE_SYSTEM_ZLIB)
1030 EXPECT_EQ(uncompressed_size1
, uncompressed_size2
);
1031 EXPECT_EQ(uncompressed_size1
, uncompressed_size4
);
1032 EXPECT_EQ(compressed_size2
, compressed_size4
);
1034 // Expect frames 3 & 4 to be the same.
1035 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *frame4
);
1037 // Expect frames 3 to be the same as a uncompressed frame created
1039 framer
.set_enable_compression(false);
1040 scoped_ptr
<SpdyFrame
> uncompressed_frame(
1041 framer
.SerializeSynStream(syn_stream
));
1042 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *uncompressed_frame
);
1045 TEST_P(SpdyFramerTest
, CompressEmptyHeaders
) {
1046 // See crbug.com/172383
1047 SpdyHeadersIR
headers(1);
1048 headers
.SetHeader("server", "SpdyServer 1.0");
1049 headers
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1050 headers
.SetHeader("status", "200");
1051 headers
.SetHeader("version", "HTTP/1.1");
1052 headers
.SetHeader("content-type", "text/html");
1053 headers
.SetHeader("content-length", "12");
1054 headers
.SetHeader("x-empty-header", "");
1056 SpdyFramer
framer(spdy_version_
);
1057 framer
.set_enable_compression(true);
1058 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeHeaders(headers
));
1061 TEST_P(SpdyFramerTest
, Basic
) {
1062 const unsigned char kV2Input
[] = {
1063 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1064 0x00, 0x00, 0x00, 0x14,
1065 0x00, 0x00, 0x00, 0x01,
1066 0x00, 0x00, 0x00, 0x00,
1067 0x00, 0x00, 0x00, 0x01,
1068 0x00, 0x02, 'h', 'h',
1069 0x00, 0x02, 'v', 'v',
1071 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
1072 0x00, 0x00, 0x00, 0x18,
1073 0x00, 0x00, 0x00, 0x01,
1074 0x00, 0x00, 0x00, 0x02,
1075 0x00, 0x02, 'h', '2',
1076 0x00, 0x02, 'v', '2',
1077 0x00, 0x02, 'h', '3',
1078 0x00, 0x02, 'v', '3',
1080 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1081 0x00, 0x00, 0x00, 0x0c,
1082 0xde, 0xad, 0xbe, 0xef,
1083 0xde, 0xad, 0xbe, 0xef,
1084 0xde, 0xad, 0xbe, 0xef,
1086 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1087 0x00, 0x00, 0x00, 0x0c,
1088 0x00, 0x00, 0x00, 0x03,
1089 0x00, 0x00, 0x00, 0x00,
1090 0x00, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1093 0x00, 0x00, 0x00, 0x08,
1094 0xde, 0xad, 0xbe, 0xef,
1095 0xde, 0xad, 0xbe, 0xef,
1097 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1098 0x00, 0x00, 0x00, 0x04,
1099 0xde, 0xad, 0xbe, 0xef,
1101 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1102 0x00, 0x00, 0x00, 0x08,
1103 0x00, 0x00, 0x00, 0x01,
1104 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1106 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1107 0x00, 0x00, 0x00, 0x00,
1109 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1110 0x00, 0x00, 0x00, 0x08,
1111 0x00, 0x00, 0x00, 0x03,
1112 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1115 const unsigned char kV3Input
[] = {
1116 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1117 0x00, 0x00, 0x00, 0x1a,
1118 0x00, 0x00, 0x00, 0x01,
1119 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x01, 0x00, 0x00,
1122 0x00, 0x02, 'h', 'h',
1123 0x00, 0x00, 0x00, 0x02,
1126 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
1127 0x00, 0x00, 0x00, 0x20,
1128 0x00, 0x00, 0x00, 0x01,
1129 0x00, 0x00, 0x00, 0x02,
1130 0x00, 0x00, 0x00, 0x02,
1132 0x00, 0x00, 0x00, 0x02,
1133 'v', '2', 0x00, 0x00,
1134 0x00, 0x02, 'h', '3',
1135 0x00, 0x00, 0x00, 0x02,
1138 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1139 0x00, 0x00, 0x00, 0x0c,
1140 0xde, 0xad, 0xbe, 0xef,
1141 0xde, 0xad, 0xbe, 0xef,
1142 0xde, 0xad, 0xbe, 0xef,
1144 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1145 0x00, 0x00, 0x00, 0x0e,
1146 0x00, 0x00, 0x00, 0x03,
1147 0x00, 0x00, 0x00, 0x00,
1148 0x00, 0x00, 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1152 0x00, 0x00, 0x00, 0x08,
1153 0xde, 0xad, 0xbe, 0xef,
1154 0xde, 0xad, 0xbe, 0xef,
1156 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1157 0x00, 0x00, 0x00, 0x04,
1158 0xde, 0xad, 0xbe, 0xef,
1160 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1161 0x00, 0x00, 0x00, 0x08,
1162 0x00, 0x00, 0x00, 0x01,
1163 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1165 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1166 0x00, 0x00, 0x00, 0x00,
1168 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1169 0x00, 0x00, 0x00, 0x08,
1170 0x00, 0x00, 0x00, 0x03,
1171 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1174 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1175 // HEADERS frames with PRIORITY and END_HEADERS set.
1176 const unsigned char kV4Input
[] = {
1177 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1178 0x24, 0x00, 0x00, 0x00,
1179 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1180 0x00, 0x82, // :method: GET
1182 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1183 0x04, 0x00, 0x00, 0x00, // Stream 1
1184 0x01, 0x8c, // :status: 200
1186 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1187 0x00, 0x00, 0x00, 0x00,
1188 0x01, 0xde, 0xad, 0xbe,
1189 0xef, 0xde, 0xad, 0xbe,
1190 0xef, 0xde, 0xad, 0xbe,
1193 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1194 0x24, 0x00, 0x00, 0x00,
1195 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1196 0x00, 0x82, // :method: GET
1198 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1199 0x00, 0x00, 0x00, 0x00,
1200 0x03, 0xde, 0xad, 0xbe,
1201 0xef, 0xde, 0xad, 0xbe,
1204 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1205 0x00, 0x00, 0x00, 0x00,
1206 0x01, 0xde, 0xad, 0xbe,
1209 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1210 0x00, 0x00, 0x00, 0x00,
1211 0x01, 0x00, 0x00, 0x00,
1212 0x08, // RST_STREAM_CANCEL
1214 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1215 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1219 0x00, 0x00, 0x00, 0x00,
1220 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1221 0x08, 0x52, 0x45, 0x53, // opaque data
1222 0x45, 0x54, 0x53, 0x54,
1223 0x52, 0x45, 0x41, 0x4d,
1226 TestSpdyVisitor
visitor(spdy_version_
);
1228 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1229 } else if (IsSpdy3()) {
1230 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1232 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1235 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1236 EXPECT_EQ(24, visitor
.data_bytes_
);
1237 EXPECT_EQ(0, visitor
.error_count_
);
1238 EXPECT_EQ(2, visitor
.fin_frame_count_
);
1241 EXPECT_EQ(3, visitor
.headers_frame_count_
);
1242 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1243 base::StringPiece reset_stream
= "RESETSTREAM";
1244 EXPECT_EQ(reset_stream
, visitor
.fin_opaque_data_
);
1246 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1247 EXPECT_EQ(2, visitor
.syn_frame_count_
);
1248 EXPECT_TRUE(visitor
.fin_opaque_data_
.empty());
1251 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1252 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
1253 EXPECT_EQ(4, visitor
.data_frame_count_
);
1254 visitor
.fin_opaque_data_
.clear();
1257 // Test that the FIN flag on a data frame signifies EOF.
1258 TEST_P(SpdyFramerTest
, FinOnDataFrame
) {
1259 const unsigned char kV2Input
[] = {
1260 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1261 0x00, 0x00, 0x00, 0x14,
1262 0x00, 0x00, 0x00, 0x01,
1263 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x01,
1265 0x00, 0x02, 'h', 'h',
1266 0x00, 0x02, 'v', 'v',
1268 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1269 0x00, 0x00, 0x00, 0x10,
1270 0x00, 0x00, 0x00, 0x01,
1271 0x00, 0x00, 0x00, 0x01,
1272 0x00, 0x02, 'a', 'a',
1273 0x00, 0x02, 'b', 'b',
1275 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1276 0x00, 0x00, 0x00, 0x0c,
1277 0xde, 0xad, 0xbe, 0xef,
1278 0xde, 0xad, 0xbe, 0xef,
1279 0xde, 0xad, 0xbe, 0xef,
1281 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1282 0x01, 0x00, 0x00, 0x04,
1283 0xde, 0xad, 0xbe, 0xef,
1285 const unsigned char kV3Input
[] = {
1286 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1287 0x00, 0x00, 0x00, 0x1a,
1288 0x00, 0x00, 0x00, 0x01,
1289 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00,
1291 0x00, 0x01, 0x00, 0x00,
1292 0x00, 0x02, 'h', 'h',
1293 0x00, 0x00, 0x00, 0x02,
1296 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1297 0x00, 0x00, 0x00, 0x14,
1298 0x00, 0x00, 0x00, 0x01,
1299 0x00, 0x00, 0x00, 0x01,
1300 0x00, 0x00, 0x00, 0x02,
1301 'a', 'a', 0x00, 0x00,
1302 0x00, 0x02, 'b', 'b',
1304 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1305 0x00, 0x00, 0x00, 0x0c,
1306 0xde, 0xad, 0xbe, 0xef,
1307 0xde, 0xad, 0xbe, 0xef,
1308 0xde, 0xad, 0xbe, 0xef,
1310 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1311 0x01, 0x00, 0x00, 0x04,
1312 0xde, 0xad, 0xbe, 0xef,
1315 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1316 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1317 const unsigned char kV4Input
[] = {
1318 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1319 0x24, 0x00, 0x00, 0x00, // Stream 1
1320 0x01, 0x00, 0x00, 0x00, // Priority 0
1321 0x00, 0x82, // :method: GET
1323 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1324 0x04, 0x00, 0x00, 0x00, // Stream 1
1325 0x01, 0x8c, // :status: 200
1327 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1328 0x00, 0x00, 0x00, 0x00,
1329 0x01, 0xde, 0xad, 0xbe,
1330 0xef, 0xde, 0xad, 0xbe,
1331 0xef, 0xde, 0xad, 0xbe,
1334 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1335 0x01, 0x00, 0x00, 0x00,
1336 0x01, 0xde, 0xad, 0xbe,
1340 TestSpdyVisitor
visitor(spdy_version_
);
1342 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1343 } else if (IsSpdy3()) {
1344 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1346 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1349 EXPECT_EQ(0, visitor
.error_count_
);
1351 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1352 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1353 EXPECT_EQ(2, visitor
.headers_frame_count_
);
1355 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1356 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1357 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1359 EXPECT_EQ(16, visitor
.data_bytes_
);
1360 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1361 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1362 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1363 EXPECT_EQ(2, visitor
.data_frame_count_
);
1366 // Test that the FIN flag on a SYN reply frame signifies EOF.
1367 TEST_P(SpdyFramerTest
, FinOnSynReplyFrame
) {
1368 const unsigned char kV2Input
[] = {
1369 0x80, spdy_version_ch_
, 0x00, // SYN Stream #1
1370 0x01, 0x00, 0x00, 0x00,
1371 0x14, 0x00, 0x00, 0x00,
1372 0x01, 0x00, 0x00, 0x00,
1373 0x00, 0x00, 0x00, 0x00,
1374 0x01, 0x00, 0x02, 'h',
1375 'h', 0x00, 0x02, 'v',
1378 0x80, spdy_version_ch_
, 0x00, // SYN REPLY Stream #1
1379 0x02, 0x01, 0x00, 0x00,
1380 0x10, 0x00, 0x00, 0x00,
1381 0x01, 0x00, 0x00, 0x00,
1382 0x01, 0x00, 0x02, 'a',
1383 'a', 0x00, 0x02, 'b',
1386 const unsigned char kV3Input
[] = {
1387 0x80, spdy_version_ch_
, 0x00, // SYN Stream #1
1388 0x01, 0x00, 0x00, 0x00,
1389 0x1a, 0x00, 0x00, 0x00,
1390 0x01, 0x00, 0x00, 0x00,
1391 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x01, 0x00,
1393 0x00, 0x00, 0x02, 'h',
1394 'h', 0x00, 0x00, 0x00,
1397 0x80, spdy_version_ch_
, 0x00, // SYN REPLY Stream #1
1398 0x02, 0x01, 0x00, 0x00,
1399 0x14, 0x00, 0x00, 0x00,
1400 0x01, 0x00, 0x00, 0x00,
1401 0x01, 0x00, 0x00, 0x00,
1402 0x02, 'a', 'a', 0x00,
1403 0x00, 0x00, 0x02, 'b',
1407 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1408 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1409 const unsigned char kV4Input
[] = {
1410 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1411 0x24, 0x00, 0x00, 0x00,
1412 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1413 0x00, 0x82, // :method: GET
1415 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1416 0x05, 0x00, 0x00, 0x00,
1417 0x01, 0x8c, // Stream 1, :status: 200
1420 TestSpdyVisitor
visitor(spdy_version_
);
1422 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1423 } else if (IsSpdy3()) {
1424 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1426 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1429 EXPECT_EQ(0, visitor
.error_count_
);
1431 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1432 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1433 EXPECT_EQ(2, visitor
.headers_frame_count_
);
1435 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1436 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1437 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1439 EXPECT_EQ(0, visitor
.data_bytes_
);
1440 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1441 EXPECT_EQ(1, visitor
.fin_flag_count_
);
1442 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1443 EXPECT_EQ(0, visitor
.data_frame_count_
);
1446 TEST_P(SpdyFramerTest
, HeaderCompression
) {
1447 if (spdy_version_
> SPDY3
) {
1448 // Deflate compression doesn't apply to HPACK.
1451 SpdyFramer
send_framer(spdy_version_
);
1452 SpdyFramer
recv_framer(spdy_version_
);
1454 send_framer
.set_enable_compression(true);
1455 recv_framer
.set_enable_compression(true);
1457 const char kHeader1
[] = "header1";
1458 const char kHeader2
[] = "header2";
1459 const char kHeader3
[] = "header3";
1460 const char kValue1
[] = "value1";
1461 const char kValue2
[] = "value2";
1462 const char kValue3
[] = "value3";
1465 SpdyHeaderBlock block
;
1466 block
[kHeader1
] = kValue1
;
1467 block
[kHeader2
] = kValue2
;
1468 SpdySynStreamIR
syn_ir_1(1);
1469 syn_ir_1
.set_name_value_block(block
);
1470 scoped_ptr
<SpdyFrame
> syn_frame_1(send_framer
.SerializeFrame(syn_ir_1
));
1471 EXPECT_TRUE(syn_frame_1
.get() != NULL
);
1474 block
[kHeader3
] = kValue3
;
1475 SpdySynStreamIR
syn_stream(3);
1476 syn_stream
.set_name_value_block(block
);
1477 scoped_ptr
<SpdyFrame
> syn_frame_2(send_framer
.SerializeSynStream(syn_stream
));
1478 EXPECT_TRUE(syn_frame_2
.get() != NULL
);
1480 // Now start decompressing
1481 scoped_ptr
<SpdyFrame
> decompressed
;
1482 scoped_ptr
<SpdyFrame
> uncompressed
;
1483 base::StringPiece serialized_headers
;
1484 SpdyHeaderBlock decompressed_headers
;
1486 // Decompress SYN_STREAM #1
1488 SpdyFramerTestUtil::DecompressFrame(&recv_framer
, *syn_frame_1
));
1489 EXPECT_TRUE(decompressed
.get() != NULL
);
1490 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1491 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1492 serialized_headers
.size(),
1493 &decompressed_headers
));
1494 EXPECT_EQ(2u, decompressed_headers
.size());
1495 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1496 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1498 // Decompress SYN_STREAM #2
1500 SpdyFramerTestUtil::DecompressFrame(&recv_framer
, *syn_frame_2
));
1501 EXPECT_TRUE(decompressed
.get() != NULL
);
1502 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1503 decompressed_headers
.clear();
1504 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1505 serialized_headers
.size(),
1506 &decompressed_headers
));
1507 EXPECT_EQ(3u, decompressed_headers
.size());
1508 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1509 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1510 EXPECT_EQ(kValue3
, decompressed_headers
[kHeader3
]);
1513 // Verify we can decompress the stream even if handed over to the
1514 // framer 1 byte at a time.
1515 TEST_P(SpdyFramerTest
, UnclosedStreamDataCompressorsOneByteAtATime
) {
1516 SpdyFramer
send_framer(spdy_version_
);
1518 send_framer
.set_enable_compression(true);
1520 const char kHeader1
[] = "header1";
1521 const char kHeader2
[] = "header2";
1522 const char kValue1
[] = "value1";
1523 const char kValue2
[] = "value2";
1525 SpdyHeadersIR
headers(1);
1526 headers
.SetHeader(kHeader1
, kValue1
);
1527 headers
.SetHeader(kHeader2
, kValue2
);
1528 scoped_ptr
<SpdyFrame
> headers_frame(send_framer
.SerializeHeaders(headers
));
1529 EXPECT_TRUE(headers_frame
.get() != NULL
);
1531 const char bytes
[] = "this is a test test test test test!";
1532 SpdyDataIR
data_ir(1, StringPiece(bytes
, arraysize(bytes
)));
1533 data_ir
.set_fin(true);
1534 scoped_ptr
<SpdyFrame
> send_frame(send_framer
.SerializeData(data_ir
));
1535 EXPECT_TRUE(send_frame
.get() != NULL
);
1537 // Run the inputs through the framer.
1538 TestSpdyVisitor
visitor(spdy_version_
);
1539 visitor
.use_compression_
= true;
1540 const unsigned char* data
;
1541 data
= reinterpret_cast<const unsigned char*>(headers_frame
->data());
1542 for (size_t idx
= 0; idx
< headers_frame
->size(); ++idx
) {
1543 visitor
.SimulateInFramer(data
+ idx
, 1);
1544 ASSERT_EQ(0, visitor
.error_count_
);
1546 data
= reinterpret_cast<const unsigned char*>(send_frame
->data());
1547 for (size_t idx
= 0; idx
< send_frame
->size(); ++idx
) {
1548 visitor
.SimulateInFramer(data
+ idx
, 1);
1549 ASSERT_EQ(0, visitor
.error_count_
);
1552 EXPECT_EQ(0, visitor
.error_count_
);
1553 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1554 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1555 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1556 EXPECT_EQ(arraysize(bytes
), static_cast<unsigned>(visitor
.data_bytes_
));
1557 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1558 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1559 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1560 EXPECT_EQ(1, visitor
.data_frame_count_
);
1563 TEST_P(SpdyFramerTest
, WindowUpdateFrame
) {
1564 SpdyFramer
framer(spdy_version_
);
1565 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
1566 SpdyWindowUpdateIR(1, 0x12345678)));
1568 const char kDescription
[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1569 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1570 0x80, spdy_version_ch_
, 0x00, 0x09,
1571 0x00, 0x00, 0x00, 0x08,
1572 0x00, 0x00, 0x00, 0x01,
1573 0x12, 0x34, 0x56, 0x78
1575 const unsigned char kV4FrameData
[] = {
1576 0x00, 0x00, 0x04, 0x08,
1577 0x00, 0x00, 0x00, 0x00,
1578 0x01, 0x12, 0x34, 0x56,
1583 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1585 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1589 TEST_P(SpdyFramerTest
, CreateDataFrame
) {
1590 SpdyFramer
framer(spdy_version_
);
1593 const char kDescription
[] = "'hello' data frame, no FIN";
1594 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1595 0x00, 0x00, 0x00, 0x01,
1596 0x00, 0x00, 0x00, 0x05,
1600 const unsigned char kV4FrameData
[] = {
1601 0x00, 0x00, 0x05, 0x00,
1602 0x00, 0x00, 0x00, 0x00,
1603 0x01, 'h', 'e', 'l',
1606 const char bytes
[] = "hello";
1608 SpdyDataIR
data_ir(1, bytes
);
1609 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1612 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1615 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1618 SpdyDataIR
data_header_ir(1);
1619 data_header_ir
.SetDataShallow(bytes
);
1620 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(
1622 CompareCharArraysWithHexError(
1624 reinterpret_cast<const unsigned char*>(frame
->data()),
1625 framer
.GetDataFrameMinimumSize(),
1626 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1627 framer
.GetDataFrameMinimumSize());
1631 const char kDescription
[] = "'hello' data frame with more padding, no FIN";
1632 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1633 0x00, 0x00, 0x00, 0x01,
1634 0x00, 0x00, 0x00, 0x05,
1639 const unsigned char kV4FrameData
[] = {
1640 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1641 0x08, 0x00, 0x00, 0x00,
1642 0x01, 0xf7, // Pad length field.
1643 'h', 'e', 'l', 'l', // Data
1645 // Padding of 247 0x00(s).
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1668 const char bytes
[] = "hello";
1670 SpdyDataIR
data_ir(1, bytes
);
1671 // 247 zeros and the pad length field make the overall padding to be 248
1673 data_ir
.set_padding_len(248);
1674 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1677 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1680 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1683 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1684 CompareCharArraysWithHexError(
1686 reinterpret_cast<const unsigned char*>(frame
->data()),
1687 framer
.GetDataFrameMinimumSize(),
1688 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1689 framer
.GetDataFrameMinimumSize());
1693 const char kDescription
[] = "'hello' data frame with few padding, no FIN";
1694 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1695 0x00, 0x00, 0x00, 0x01,
1696 0x00, 0x00, 0x00, 0x05,
1701 const unsigned char kV4FrameData
[] = {
1702 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1703 0x08, 0x00, 0x00, 0x00,
1704 0x01, 0x07, // Pad length field.
1705 'h', 'e', 'l', 'l', // Data
1707 0x00, 0x00, 0x00, 0x00, // Padding
1710 const char bytes
[] = "hello";
1712 SpdyDataIR
data_ir(1, bytes
);
1713 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1714 data_ir
.set_padding_len(8);
1715 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1718 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1721 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1726 const char kDescription
[] =
1727 "'hello' data frame with 1 byte padding, no FIN";
1728 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1729 0x00, 0x00, 0x00, 0x01,
1730 0x00, 0x00, 0x00, 0x05,
1735 const unsigned char kV4FrameData
[] = {
1736 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1737 0x08, 0x00, 0x00, 0x00,
1738 0x01, 0x00, // Pad length field.
1739 'h', 'e', 'l', 'l', // Data
1742 const char bytes
[] = "hello";
1744 SpdyDataIR
data_ir(1, bytes
);
1745 // The pad length field itself is used for the 1-byte padding and no padding
1746 // payload is needed.
1747 data_ir
.set_padding_len(1);
1748 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1751 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1754 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1757 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1758 CompareCharArraysWithHexError(
1760 reinterpret_cast<const unsigned char*>(frame
->data()),
1761 framer
.GetDataFrameMinimumSize(),
1762 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1763 framer
.GetDataFrameMinimumSize());
1767 const char kDescription
[] = "Data frame with negative data byte, no FIN";
1768 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1769 0x00, 0x00, 0x00, 0x01,
1770 0x00, 0x00, 0x00, 0x01,
1773 const unsigned char kV4FrameData
[] = {
1774 0x00, 0x00, 0x01, 0x00, 0x00,
1775 0x00, 0x00, 0x00, 0x01,
1778 SpdyDataIR
data_ir(1, "\xff");
1779 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1782 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1785 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1790 const char kDescription
[] = "'hello' data frame, with FIN";
1791 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1792 0x00, 0x00, 0x00, 0x01,
1793 0x01, 0x00, 0x00, 0x05,
1797 const unsigned char kV4FrameData
[] = {
1798 0x00, 0x00, 0x05, 0x00,
1799 0x01, 0x00, 0x00, 0x00,
1800 0x01, 'h', 'e', 'l',
1803 SpdyDataIR
data_ir(1, "hello");
1804 data_ir
.set_fin(true);
1805 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1808 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1811 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1816 const char kDescription
[] = "Empty data frame";
1817 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1818 0x00, 0x00, 0x00, 0x01,
1819 0x00, 0x00, 0x00, 0x00,
1821 const unsigned char kV4FrameData
[] = {
1822 0x00, 0x00, 0x00, 0x00,
1823 0x00, 0x00, 0x00, 0x00,
1826 SpdyDataIR
data_ir(1, "");
1827 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1830 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1833 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1836 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1837 CompareCharArraysWithHexError(
1839 reinterpret_cast<const unsigned char*>(frame
->data()),
1840 framer
.GetDataFrameMinimumSize(),
1841 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1842 framer
.GetDataFrameMinimumSize());
1846 const char kDescription
[] = "Data frame with max stream ID";
1847 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1848 0x7f, 0xff, 0xff, 0xff,
1849 0x01, 0x00, 0x00, 0x05,
1853 const unsigned char kV4FrameData
[] = {
1854 0x00, 0x00, 0x05, 0x00,
1855 0x01, 0x7f, 0xff, 0xff,
1856 0xff, 'h', 'e', 'l',
1859 SpdyDataIR
data_ir(0x7fffffff, "hello");
1860 data_ir
.set_fin(true);
1861 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1864 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1867 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1872 // This test does not apply to SPDY 4 because the max frame size is smaller
1874 const char kDescription
[] = "Large data frame";
1875 const int kDataSize
= 4 * 1024 * 1024; // 4 MB
1876 const string
kData(kDataSize
, 'A');
1877 const unsigned char kFrameHeader
[] = {
1878 0x00, 0x00, 0x00, 0x01,
1879 0x01, 0x40, 0x00, 0x00,
1882 const int kFrameSize
= arraysize(kFrameHeader
) + kDataSize
;
1883 scoped_ptr
<unsigned char[]> expected_frame_data(
1884 new unsigned char[kFrameSize
]);
1885 memcpy(expected_frame_data
.get(), kFrameHeader
, arraysize(kFrameHeader
));
1886 memset(expected_frame_data
.get() + arraysize(kFrameHeader
), 'A', kDataSize
);
1888 SpdyDataIR
data_ir(1, kData
);
1889 data_ir
.set_fin(true);
1890 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1891 CompareFrame(kDescription
, *frame
, expected_frame_data
.get(), kFrameSize
);
1895 TEST_P(SpdyFramerTest
, CreateSynStreamUncompressed
) {
1896 if (!IsSpdy2() && !IsSpdy3()) {
1897 // SYN_STREAM unsupported in SPDY>3
1900 SpdyFramer
framer(spdy_version_
);
1901 framer
.set_enable_compression(false);
1904 const char kDescription
[] = "SYN_STREAM frame, lowest pri, no FIN";
1906 const unsigned char kPri
= IsSpdy2() ? 0xC0 : 0xE0;
1907 const unsigned char kV2FrameData
[] = {
1908 0x80, spdy_version_ch_
, 0x00, 0x01,
1909 0x00, 0x00, 0x00, 0x20,
1910 0x00, 0x00, 0x00, 0x01,
1911 0x00, 0x00, 0x00, 0x00,
1912 kPri
, 0x00, 0x00, 0x02,
1913 0x00, 0x03, 'b', 'a',
1914 'r', 0x00, 0x03, 'f',
1915 'o', 'o', 0x00, 0x03,
1916 'f', 'o', 'o', 0x00,
1919 const unsigned char kV3FrameData
[] = {
1920 0x80, spdy_version_ch_
, 0x00, 0x01,
1921 0x00, 0x00, 0x00, 0x2a,
1922 0x00, 0x00, 0x00, 0x01,
1923 0x00, 0x00, 0x00, 0x00,
1924 kPri
, 0x00, 0x00, 0x00,
1925 0x00, 0x02, 0x00, 0x00,
1926 0x00, 0x03, 'b', 'a',
1927 'r', 0x00, 0x00, 0x00,
1928 0x03, 'f', 'o', 'o',
1929 0x00, 0x00, 0x00, 0x03,
1930 'f', 'o', 'o', 0x00,
1931 0x00, 0x00, 0x03, 'b',
1934 SpdySynStreamIR
syn_stream(1);
1935 syn_stream
.set_priority(framer
.GetLowestPriority());
1936 syn_stream
.SetHeader("bar", "foo");
1937 syn_stream
.SetHeader("foo", "bar");
1938 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1940 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1941 } else if (IsSpdy3()) {
1942 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1944 LOG(FATAL
) << "Unsupported version in test.";
1949 const char kDescription
[] =
1950 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1953 const unsigned char kV2FrameData
[] = {
1954 0x80, spdy_version_ch_
, 0x00, 0x01,
1955 0x01, 0x00, 0x00, 0x1D,
1956 0x7f, 0xff, 0xff, 0xff,
1957 0x7f, 0xff, 0xff, 0xff,
1958 0x00, 0x00, 0x00, 0x02,
1959 0x00, 0x00, 0x00, 0x03,
1960 'f', 'o', 'o', 0x00,
1961 0x03, 'f', 'o', 'o',
1962 0x00, 0x03, 'b', 'a',
1965 const unsigned char kV3FrameData
[] = {
1966 0x80, spdy_version_ch_
, 0x00, 0x01,
1967 0x01, 0x00, 0x00, 0x27,
1968 0x7f, 0xff, 0xff, 0xff,
1969 0x7f, 0xff, 0xff, 0xff,
1970 0x00, 0x00, 0x00, 0x00,
1971 0x00, 0x02, 0x00, 0x00,
1972 0x00, 0x00, 0x00, 0x00,
1973 0x00, 0x03, 'f', 'o',
1974 'o', 0x00, 0x00, 0x00,
1975 0x03, 'f', 'o', 'o',
1976 0x00, 0x00, 0x00, 0x03,
1979 SpdySynStreamIR
syn_stream(0x7fffffff);
1980 syn_stream
.set_associated_to_stream_id(0x7fffffff);
1981 syn_stream
.set_priority(framer
.GetHighestPriority());
1982 syn_stream
.set_fin(true);
1983 syn_stream
.SetHeader("", "foo");
1984 syn_stream
.SetHeader("foo", "bar");
1985 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1987 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1988 } else if (IsSpdy3()) {
1989 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1991 LOG(FATAL
) << "Unsupported version in test.";
1996 const char kDescription
[] =
1997 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
2000 const unsigned char kPri
= IsSpdy2() ? 0x40 : 0x20;
2001 const unsigned char kV2FrameData
[] = {
2002 0x80, spdy_version_ch_
, 0x00, 0x01,
2003 0x01, 0x00, 0x00, 0x1D,
2004 0x7f, 0xff, 0xff, 0xff,
2005 0x7f, 0xff, 0xff, 0xff,
2006 kPri
, 0x00, 0x00, 0x02,
2007 0x00, 0x03, 'b', 'a',
2008 'r', 0x00, 0x03, 'f',
2009 'o', 'o', 0x00, 0x03,
2010 'f', 'o', 'o', 0x00,
2013 const unsigned char kV3FrameData
[] = {
2014 0x80, spdy_version_ch_
, 0x00, 0x01,
2015 0x01, 0x00, 0x00, 0x27,
2016 0x7f, 0xff, 0xff, 0xff,
2017 0x7f, 0xff, 0xff, 0xff,
2018 kPri
, 0x00, 0x00, 0x00,
2019 0x00, 0x02, 0x00, 0x00,
2020 0x00, 0x03, 'b', 'a',
2021 'r', 0x00, 0x00, 0x00,
2022 0x03, 'f', 'o', 'o',
2023 0x00, 0x00, 0x00, 0x03,
2024 'f', 'o', 'o', 0x00,
2027 SpdySynStreamIR
syn_stream(0x7fffffff);
2028 syn_stream
.set_associated_to_stream_id(0x7fffffff);
2029 syn_stream
.set_priority(1);
2030 syn_stream
.set_fin(true);
2031 syn_stream
.SetHeader("bar", "foo");
2032 syn_stream
.SetHeader("foo", "");
2033 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
2035 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2036 } else if (IsSpdy3()) {
2037 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2039 LOG(FATAL
) << "Unsupported version in test.";
2044 // TODO(phajdan.jr): Clean up after we no longer need
2045 // to workaround http://crbug.com/139744.
2046 #if !defined(USE_SYSTEM_ZLIB)
2047 TEST_P(SpdyFramerTest
, CreateSynStreamCompressed
) {
2048 if (!IsSpdy2() && !IsSpdy3()) {
2049 // SYN_STREAM not supported for SPDY>3
2052 SpdyFramer
framer(spdy_version_
);
2053 framer
.set_enable_compression(true);
2056 const char kDescription
[] =
2057 "SYN_STREAM frame, low pri, no FIN";
2058 const SpdyPriority priority
= IsSpdy2() ? 2 : 4;
2060 const unsigned char kV2FrameData
[] = {
2061 0x80, spdy_version_ch_
, 0x00, 0x01,
2062 0x00, 0x00, 0x00, 0x36,
2063 0x00, 0x00, 0x00, 0x01,
2064 0x00, 0x00, 0x00, 0x00,
2065 0x80, 0x00, 0x38, 0xea,
2066 0xdf, 0xa2, 0x51, 0xb2,
2067 0x62, 0x60, 0x62, 0x60,
2068 0x4e, 0x4a, 0x2c, 0x62,
2069 0x60, 0x06, 0x08, 0xa0,
2070 0xb4, 0xfc, 0x7c, 0x80,
2071 0x00, 0x62, 0x60, 0x4e,
2072 0xcb, 0xcf, 0x67, 0x60,
2073 0x06, 0x08, 0xa0, 0xa4,
2074 0xc4, 0x22, 0x80, 0x00,
2075 0x02, 0x00, 0x00, 0x00,
2078 const unsigned char kV3FrameData
[] = {
2079 0x80, spdy_version_ch_
, 0x00, 0x01,
2080 0x00, 0x00, 0x00, 0x37,
2081 0x00, 0x00, 0x00, 0x01,
2082 0x00, 0x00, 0x00, 0x00,
2083 0x80, 0x00, 0x38, 0xEA,
2084 0xE3, 0xC6, 0xA7, 0xC2,
2085 0x02, 0xE5, 0x0E, 0x50,
2086 0xC2, 0x4B, 0x4A, 0x04,
2087 0xE5, 0x0B, 0x66, 0x80,
2088 0x00, 0x4A, 0xCB, 0xCF,
2089 0x07, 0x08, 0x20, 0x10,
2090 0x95, 0x96, 0x9F, 0x0F,
2091 0xA2, 0x00, 0x02, 0x28,
2092 0x29, 0xB1, 0x08, 0x20,
2093 0x80, 0x00, 0x00, 0x00,
2096 const unsigned char kV2SIMDFrameData
[] = {
2097 0x80, spdy_version_ch_
, 0x00, 0x01,
2098 0x00, 0x00, 0x00, 0x33,
2099 0x00, 0x00, 0x00, 0x01,
2100 0x00, 0x00, 0x00, 0x00,
2101 0x80, 0x00, 0x38, 0xea,
2102 0xdf, 0xa2, 0x51, 0xb2,
2103 0x62, 0x60, 0x62, 0x60,
2104 0x4e, 0x4a, 0x2c, 0x62,
2105 0x60, 0x06, 0x08, 0xa0,
2106 0xb4, 0xfc, 0x7c, 0x80,
2107 0x00, 0x62, 0x60, 0x06,
2108 0x13, 0x00, 0x01, 0x94,
2109 0x94, 0x58, 0x04, 0x10,
2110 0x40, 0x00, 0x00, 0x00,
2113 const unsigned char kV3SIMDFrameData
[] = {
2114 0x80, spdy_version_ch_
, 0x00, 0x01,
2115 0x00, 0x00, 0x00, 0x32,
2116 0x00, 0x00, 0x00, 0x01,
2117 0x00, 0x00, 0x00, 0x00,
2118 0x80, 0x00, 0x38, 0xea,
2119 0xe3, 0xc6, 0xa7, 0xc2,
2120 0x02, 0xe5, 0x0e, 0x50,
2121 0xc2, 0x4b, 0x4a, 0x04,
2122 0xe5, 0x0b, 0x66, 0x80,
2123 0x00, 0x4a, 0xcb, 0xcf,
2124 0x07, 0x08, 0x20, 0x24,
2125 0x0a, 0x20, 0x80, 0x92,
2126 0x12, 0x8b, 0x00, 0x02,
2127 0x08, 0x00, 0x00, 0x00,
2131 SpdySynStreamIR
syn_stream(1);
2132 syn_stream
.set_priority(priority
);
2133 syn_stream
.SetHeader("bar", "foo");
2134 syn_stream
.SetHeader("foo", "bar");
2135 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
2136 const unsigned char* frame_data
=
2137 reinterpret_cast<const unsigned char*>(frame
->data());
2139 // Try comparing with SIMD version, if that fails, do a failing check
2140 // with pretty printing against non-SIMD version
2141 if (memcmp(frame_data
,
2143 std::min(arraysize(kV2SIMDFrameData
), frame
->size())) != 0) {
2144 CompareCharArraysWithHexError(kDescription
,
2148 arraysize(kV2FrameData
));
2150 } else if (IsSpdy3()) {
2151 if (memcmp(frame_data
,
2153 std::min(arraysize(kV3SIMDFrameData
), frame
->size())) != 0) {
2154 CompareCharArraysWithHexError(kDescription
,
2158 arraysize(kV3FrameData
));
2161 LOG(FATAL
) << "Unsupported version in test.";
2165 #endif // !defined(USE_SYSTEM_ZLIB)
2167 TEST_P(SpdyFramerTest
, CreateSynReplyUncompressed
) {
2168 if (spdy_version_
> SPDY3
) {
2169 // SYN_REPLY unsupported in SPDY>3
2172 SpdyFramer
framer(spdy_version_
);
2173 framer
.set_enable_compression(false);
2176 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2178 const unsigned char kV2FrameData
[] = {
2179 0x80, spdy_version_ch_
, 0x00, 0x02,
2180 0x00, 0x00, 0x00, 0x1C,
2181 0x00, 0x00, 0x00, 0x01,
2182 0x00, 0x00, 0x00, 0x02,
2183 0x00, 0x03, 'b', 'a',
2184 'r', 0x00, 0x03, 'f',
2185 'o', 'o', 0x00, 0x03,
2186 'f', 'o', 'o', 0x00,
2189 const unsigned char kV3FrameData
[] = {
2190 0x80, spdy_version_ch_
, 0x00, 0x02,
2191 0x00, 0x00, 0x00, 0x24,
2192 0x00, 0x00, 0x00, 0x01,
2193 0x00, 0x00, 0x00, 0x02,
2194 0x00, 0x00, 0x00, 0x03,
2195 'b', 'a', 'r', 0x00,
2196 0x00, 0x00, 0x03, 'f',
2197 'o', 'o', 0x00, 0x00,
2198 0x00, 0x03, 'f', 'o',
2199 'o', 0x00, 0x00, 0x00,
2202 SpdySynReplyIR
syn_reply(1);
2203 syn_reply
.SetHeader("bar", "foo");
2204 syn_reply
.SetHeader("foo", "bar");
2205 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2207 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2208 } else if (IsSpdy3()) {
2209 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2211 LOG(FATAL
) << "Unsupported version in test.";
2216 const char kDescription
[] =
2217 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2219 const unsigned char kV2FrameData
[] = {
2220 0x80, spdy_version_ch_
, 0x00, 0x02,
2221 0x01, 0x00, 0x00, 0x19,
2222 0x7f, 0xff, 0xff, 0xff,
2223 0x00, 0x00, 0x00, 0x02,
2224 0x00, 0x00, 0x00, 0x03,
2225 'f', 'o', 'o', 0x00,
2226 0x03, 'f', 'o', 'o',
2227 0x00, 0x03, 'b', 'a',
2230 const unsigned char kV3FrameData
[] = {
2231 0x80, spdy_version_ch_
, 0x00, 0x02,
2232 0x01, 0x00, 0x00, 0x21,
2233 0x7f, 0xff, 0xff, 0xff,
2234 0x00, 0x00, 0x00, 0x02,
2235 0x00, 0x00, 0x00, 0x00,
2236 0x00, 0x00, 0x00, 0x03,
2237 'f', 'o', 'o', 0x00,
2238 0x00, 0x00, 0x03, 'f',
2239 'o', 'o', 0x00, 0x00,
2240 0x00, 0x03, 'b', 'a',
2243 SpdySynReplyIR
syn_reply(0x7fffffff);
2244 syn_reply
.set_fin(true);
2245 syn_reply
.SetHeader("", "foo");
2246 syn_reply
.SetHeader("foo", "bar");
2247 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2249 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2250 } else if (IsSpdy3()) {
2251 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2253 LOG(FATAL
) << "Unsupported version in test.";
2258 const char kDescription
[] =
2259 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2261 const unsigned char kV2FrameData
[] = {
2262 0x80, spdy_version_ch_
, 0x00, 0x02,
2263 0x01, 0x00, 0x00, 0x19,
2264 0x7f, 0xff, 0xff, 0xff,
2265 0x00, 0x00, 0x00, 0x02,
2266 0x00, 0x03, 'b', 'a',
2267 'r', 0x00, 0x03, 'f',
2268 'o', 'o', 0x00, 0x03,
2269 'f', 'o', 'o', 0x00,
2272 const unsigned char kV3FrameData
[] = {
2273 0x80, spdy_version_ch_
, 0x00, 0x02,
2274 0x01, 0x00, 0x00, 0x21,
2275 0x7f, 0xff, 0xff, 0xff,
2276 0x00, 0x00, 0x00, 0x02,
2277 0x00, 0x00, 0x00, 0x03,
2278 'b', 'a', 'r', 0x00,
2279 0x00, 0x00, 0x03, 'f',
2280 'o', 'o', 0x00, 0x00,
2281 0x00, 0x03, 'f', 'o',
2282 'o', 0x00, 0x00, 0x00,
2285 SpdySynReplyIR
syn_reply(0x7fffffff);
2286 syn_reply
.set_fin(true);
2287 syn_reply
.SetHeader("bar", "foo");
2288 syn_reply
.SetHeader("foo", "");
2289 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2291 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2292 } else if (IsSpdy3()) {
2293 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2295 LOG(FATAL
) << "Unsupported version in test.";
2300 // TODO(phajdan.jr): Clean up after we no longer need
2301 // to workaround http://crbug.com/139744.
2302 #if !defined(USE_SYSTEM_ZLIB)
2303 TEST_P(SpdyFramerTest
, CreateSynReplyCompressed
) {
2304 if (spdy_version_
> SPDY3
) {
2305 // SYN_REPLY unsupported in SPDY>3
2308 SpdyFramer
framer(spdy_version_
);
2309 framer
.set_enable_compression(true);
2312 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2314 const unsigned char kV2FrameData
[] = {
2315 0x80, spdy_version_ch_
, 0x00, 0x02,
2316 0x00, 0x00, 0x00, 0x32,
2317 0x00, 0x00, 0x00, 0x01,
2318 0x00, 0x00, 0x38, 0xea,
2319 0xdf, 0xa2, 0x51, 0xb2,
2320 0x62, 0x60, 0x62, 0x60,
2321 0x4e, 0x4a, 0x2c, 0x62,
2322 0x60, 0x06, 0x08, 0xa0,
2323 0xb4, 0xfc, 0x7c, 0x80,
2324 0x00, 0x62, 0x60, 0x4e,
2325 0xcb, 0xcf, 0x67, 0x60,
2326 0x06, 0x08, 0xa0, 0xa4,
2327 0xc4, 0x22, 0x80, 0x00,
2328 0x02, 0x00, 0x00, 0x00,
2331 const unsigned char kV3FrameData
[] = {
2332 0x80, spdy_version_ch_
, 0x00, 0x02,
2333 0x00, 0x00, 0x00, 0x31,
2334 0x00, 0x00, 0x00, 0x01,
2335 0x38, 0xea, 0xe3, 0xc6,
2336 0xa7, 0xc2, 0x02, 0xe5,
2337 0x0e, 0x50, 0xc2, 0x4b,
2338 0x4a, 0x04, 0xe5, 0x0b,
2339 0x66, 0x80, 0x00, 0x4a,
2340 0xcb, 0xcf, 0x07, 0x08,
2341 0x20, 0x10, 0x95, 0x96,
2342 0x9f, 0x0f, 0xa2, 0x00,
2343 0x02, 0x28, 0x29, 0xb1,
2344 0x08, 0x20, 0x80, 0x00,
2345 0x00, 0x00, 0x00, 0xff,
2348 const unsigned char kV2SIMDFrameData
[] = {
2349 0x80, spdy_version_ch_
, 0x00, 0x02,
2350 0x00, 0x00, 0x00, 0x2f,
2351 0x00, 0x00, 0x00, 0x01,
2352 0x00, 0x00, 0x38, 0xea,
2353 0xdf, 0xa2, 0x51, 0xb2,
2354 0x62, 0x60, 0x62, 0x60,
2355 0x4e, 0x4a, 0x2c, 0x62,
2356 0x60, 0x06, 0x08, 0xa0,
2357 0xb4, 0xfc, 0x7c, 0x80,
2358 0x00, 0x62, 0x60, 0x06,
2359 0x13, 0x00, 0x01, 0x94,
2360 0x94, 0x58, 0x04, 0x10,
2361 0x40, 0x00, 0x00, 0x00,
2364 const unsigned char kV3SIMDFrameData
[] = {
2365 0x80, spdy_version_ch_
, 0x00, 0x02,
2366 0x00, 0x00, 0x00, 0x2c,
2367 0x00, 0x00, 0x00, 0x01,
2368 0x38, 0xea, 0xe3, 0xc6,
2369 0xa7, 0xc2, 0x02, 0xe5,
2370 0x0e, 0x50, 0xc2, 0x4b,
2371 0x4a, 0x04, 0xe5, 0x0b,
2372 0x66, 0x80, 0x00, 0x4a,
2373 0xcb, 0xcf, 0x07, 0x08,
2374 0x20, 0x24, 0x0a, 0x20,
2375 0x80, 0x92, 0x12, 0x8b,
2376 0x00, 0x02, 0x08, 0x00,
2377 0x00, 0x00, 0xff, 0xff,
2380 SpdySynReplyIR
syn_reply(1);
2381 syn_reply
.SetHeader("bar", "foo");
2382 syn_reply
.SetHeader("foo", "bar");
2383 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2384 const unsigned char* frame_data
=
2385 reinterpret_cast<const unsigned char*>(frame
->data());
2387 // Try comparing with SIMD version, if that fails, do a failing check
2388 // with pretty printing against non-SIMD version
2389 if (memcmp(frame_data
,
2391 std::min(arraysize(kV2SIMDFrameData
), frame
->size())) != 0) {
2392 CompareCharArraysWithHexError(kDescription
,
2396 arraysize(kV2FrameData
));
2398 } else if (IsSpdy3()) {
2399 if (memcmp(frame_data
,
2401 std::min(arraysize(kV3SIMDFrameData
), frame
->size())) != 0) {
2402 CompareCharArraysWithHexError(kDescription
,
2406 arraysize(kV3FrameData
));
2409 LOG(FATAL
) << "Unsupported version in test.";
2413 #endif // !defined(USE_SYSTEM_ZLIB)
2415 TEST_P(SpdyFramerTest
, CreateRstStream
) {
2416 SpdyFramer
framer(spdy_version_
);
2419 const char kDescription
[] = "RST_STREAM frame";
2420 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2421 0x80, spdy_version_ch_
, 0x00, 0x03,
2422 0x00, 0x00, 0x00, 0x08,
2423 0x00, 0x00, 0x00, 0x01,
2424 0x00, 0x00, 0x00, 0x01,
2426 const unsigned char kV4FrameData
[] = {
2427 0x00, 0x00, 0x07, 0x03,
2428 0x00, 0x00, 0x00, 0x00,
2429 0x01, 0x00, 0x00, 0x00,
2430 0x01, 0x52, 0x53, 0x54
2432 SpdyRstStreamIR
rst_stream(1, RST_STREAM_PROTOCOL_ERROR
, "RST");
2433 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2435 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2437 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2442 const char kDescription
[] = "RST_STREAM frame with max stream ID";
2443 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2444 0x80, spdy_version_ch_
, 0x00, 0x03,
2445 0x00, 0x00, 0x00, 0x08,
2446 0x7f, 0xff, 0xff, 0xff,
2447 0x00, 0x00, 0x00, 0x01,
2449 const unsigned char kV4FrameData
[] = {
2450 0x00, 0x00, 0x04, 0x03,
2451 0x00, 0x7f, 0xff, 0xff,
2452 0xff, 0x00, 0x00, 0x00,
2455 SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2456 RST_STREAM_PROTOCOL_ERROR
,
2458 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2460 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2462 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2467 const char kDescription
[] = "RST_STREAM frame with max status code";
2468 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2469 0x80, spdy_version_ch_
, 0x00, 0x03,
2470 0x00, 0x00, 0x00, 0x08,
2471 0x7f, 0xff, 0xff, 0xff,
2472 0x00, 0x00, 0x00, 0x06,
2474 const unsigned char kV4FrameData
[] = {
2475 0x00, 0x00, 0x04, 0x03,
2476 0x00, 0x7f, 0xff, 0xff,
2477 0xff, 0x00, 0x00, 0x00,
2480 SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2481 RST_STREAM_INTERNAL_ERROR
,
2483 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2485 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2487 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2492 TEST_P(SpdyFramerTest
, CreateSettings
) {
2493 SpdyFramer
framer(spdy_version_
);
2496 const char kDescription
[] = "Network byte order SETTINGS frame";
2498 const unsigned char kV2FrameData
[] = {
2499 0x80, spdy_version_ch_
, 0x00, 0x04,
2500 0x00, 0x00, 0x00, 0x0c,
2501 0x00, 0x00, 0x00, 0x01,
2502 0x07, 0x00, 0x00, 0x01,
2503 0x0a, 0x0b, 0x0c, 0x0d,
2505 const unsigned char kV3FrameData
[] = {
2506 0x80, spdy_version_ch_
, 0x00, 0x04,
2507 0x00, 0x00, 0x00, 0x0c,
2508 0x00, 0x00, 0x00, 0x01,
2509 0x01, 0x00, 0x00, 0x07,
2510 0x0a, 0x0b, 0x0c, 0x0d,
2512 const unsigned char kV4FrameData
[] = {
2513 0x00, 0x00, 0x06, 0x04,
2514 0x00, 0x00, 0x00, 0x00,
2515 0x00, 0x00, 0x04, 0x0a,
2519 uint32 kValue
= 0x0a0b0c0d;
2520 SpdySettingsIR settings_ir
;
2522 SpdySettingsFlags kFlags
= static_cast<SpdySettingsFlags
>(0x01);
2523 SpdySettingsIds kId
= SETTINGS_INITIAL_WINDOW_SIZE
;
2524 settings_ir
.AddSetting(kId
,
2525 kFlags
& SETTINGS_FLAG_PLEASE_PERSIST
,
2526 kFlags
& SETTINGS_FLAG_PERSISTED
,
2529 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2531 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2532 } else if (IsSpdy3()) {
2533 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2535 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2540 const char kDescription
[] = "Basic SETTINGS frame";
2542 const unsigned char kV2FrameData
[] = {
2543 0x80, spdy_version_ch_
, 0x00, 0x04,
2544 0x00, 0x00, 0x00, 0x24,
2545 0x00, 0x00, 0x00, 0x04,
2546 0x01, 0x00, 0x00, 0x00, // 1st Setting
2547 0x00, 0x00, 0x00, 0x05,
2548 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2549 0x00, 0x00, 0x00, 0x06,
2550 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2551 0x00, 0x00, 0x00, 0x07,
2552 0x04, 0x00, 0x00, 0x00, // 4th Setting
2553 0x00, 0x00, 0x00, 0x08,
2555 const unsigned char kV3FrameData
[] = {
2556 0x80, spdy_version_ch_
, 0x00, 0x04,
2557 0x00, 0x00, 0x00, 0x24,
2558 0x00, 0x00, 0x00, 0x04,
2559 0x00, 0x00, 0x00, 0x01, // 1st Setting
2560 0x00, 0x00, 0x00, 0x05,
2561 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2562 0x00, 0x00, 0x00, 0x06,
2563 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2564 0x00, 0x00, 0x00, 0x07,
2565 0x00, 0x00, 0x00, 0x04, // 4th Setting
2566 0x00, 0x00, 0x00, 0x08,
2568 // These end up seemingly out of order because of the way that our internal
2569 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2571 const unsigned char kV4FrameData
[] = {
2572 0x00, 0x00, 0x18, 0x04,
2573 0x00, 0x00, 0x00, 0x00,
2574 0x00, 0x00, 0x03, // 3rd Setting
2575 0x00, 0x00, 0x00, 0x07,
2576 0x00, 0x04, // 4th Setting
2577 0x00, 0x00, 0x00, 0x08,
2578 0x00, 0x01, // 1st Setting
2579 0x00, 0x00, 0x00, 0x05,
2580 0x00, 0x02, // 2nd Setting
2581 0x00, 0x00, 0x00, 0x06,
2584 SpdySettingsIR settings_ir
;
2585 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
2589 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 2),
2593 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 3),
2597 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 4),
2601 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2604 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2605 } else if (IsSpdy3()) {
2606 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2608 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2613 const char kDescription
[] = "Empty SETTINGS frame";
2615 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2616 0x80, spdy_version_ch_
, 0x00, 0x04,
2617 0x00, 0x00, 0x00, 0x04,
2618 0x00, 0x00, 0x00, 0x00,
2620 const unsigned char kV4FrameData
[] = {
2621 0x00, 0x00, 0x00, 0x04,
2622 0x00, 0x00, 0x00, 0x00,
2625 SpdySettingsIR settings_ir
;
2626 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2628 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2630 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2635 TEST_P(SpdyFramerTest
, CreatePingFrame
) {
2636 SpdyFramer
framer(spdy_version_
);
2639 const char kDescription
[] = "PING frame";
2640 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2641 0x80, spdy_version_ch_
, 0x00, 0x06,
2642 0x00, 0x00, 0x00, 0x04,
2643 0x12, 0x34, 0x56, 0x78,
2645 const unsigned char kV4FrameData
[] = {
2646 0x00, 0x00, 0x08, 0x06,
2647 0x00, 0x00, 0x00, 0x00,
2648 0x00, 0x12, 0x34, 0x56,
2649 0x78, 0x9a, 0xbc, 0xde,
2652 const unsigned char kV4FrameDataWithAck
[] = {
2653 0x00, 0x00, 0x08, 0x06,
2654 0x01, 0x00, 0x00, 0x00,
2655 0x00, 0x12, 0x34, 0x56,
2656 0x78, 0x9a, 0xbc, 0xde,
2659 scoped_ptr
<SpdyFrame
> frame
;
2661 const SpdyPingId kPingId
= 0x123456789abcdeffULL
;
2662 SpdyPingIR
ping_ir(kPingId
);
2663 // Tests SpdyPingIR when the ping is not an ack.
2664 ASSERT_FALSE(ping_ir
.is_ack());
2665 frame
.reset(framer
.SerializePing(ping_ir
));
2666 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2668 // Tests SpdyPingIR when the ping is an ack.
2669 ping_ir
.set_is_ack(true);
2670 frame
.reset(framer
.SerializePing(ping_ir
));
2671 CompareFrame(kDescription
, *frame
,
2672 kV4FrameDataWithAck
, arraysize(kV4FrameDataWithAck
));
2675 frame
.reset(framer
.SerializePing(SpdyPingIR(0x12345678ull
)));
2676 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2681 TEST_P(SpdyFramerTest
, CreateGoAway
) {
2682 SpdyFramer
framer(spdy_version_
);
2685 const char kDescription
[] = "GOAWAY frame";
2686 const unsigned char kV2FrameData
[] = {
2687 0x80, spdy_version_ch_
, 0x00, 0x07,
2688 0x00, 0x00, 0x00, 0x04,
2689 0x00, 0x00, 0x00, 0x00, // Stream Id
2691 const unsigned char kV3FrameData
[] = {
2692 0x80, spdy_version_ch_
, 0x00, 0x07,
2693 0x00, 0x00, 0x00, 0x08,
2694 0x00, 0x00, 0x00, 0x00, // Stream Id
2695 0x00, 0x00, 0x00, 0x00, // Status
2697 const unsigned char kV4FrameData
[] = {
2698 0x00, 0x00, 0x0a, 0x07,
2699 0x00, 0x00, 0x00, 0x00,
2700 0x00, 0x00, 0x00, 0x00, // Stream id
2701 0x00, 0x00, 0x00, 0x00, // Status
2702 0x00, 0x47, 0x41, // Opaque Description
2704 SpdyGoAwayIR
goaway_ir(0, GOAWAY_OK
, "GA");
2705 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2707 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2708 } else if (IsSpdy3()) {
2709 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2711 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2716 const char kDescription
[] = "GOAWAY frame with max stream ID, status";
2717 const unsigned char kV2FrameData
[] = {
2718 0x80, spdy_version_ch_
, 0x00, 0x07,
2719 0x00, 0x00, 0x00, 0x04,
2720 0x7f, 0xff, 0xff, 0xff, // Stream Id
2722 const unsigned char kV3FrameData
[] = {
2723 0x80, spdy_version_ch_
, 0x00, 0x07,
2724 0x00, 0x00, 0x00, 0x08,
2725 0x7f, 0xff, 0xff, 0xff, // Stream Id
2726 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2728 const unsigned char kV4FrameData
[] = {
2729 0x00, 0x00, 0x0a, 0x07,
2730 0x00, 0x00, 0x00, 0x00,
2731 0x00, 0x7f, 0xff, 0xff, // Stream Id
2732 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2733 0x02, 0x47, 0x41, // Opaque Description
2735 SpdyGoAwayIR
goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR
, "GA");
2736 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2738 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2739 } else if (IsSpdy3()) {
2740 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2742 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2747 TEST_P(SpdyFramerTest
, CreateHeadersUncompressed
) {
2748 SpdyFramer
framer(spdy_version_
);
2749 framer
.set_enable_compression(false);
2752 const char kDescription
[] = "HEADERS frame, no FIN";
2754 const unsigned char kV2FrameData
[] = {
2755 0x80, spdy_version_ch_
, 0x00, 0x08,
2756 0x00, 0x00, 0x00, 0x1C,
2757 0x00, 0x00, 0x00, 0x01,
2758 0x00, 0x00, 0x00, 0x02,
2759 0x00, 0x03, 'b', 'a',
2760 'r', 0x00, 0x03, 'f',
2761 'o', 'o', 0x00, 0x03,
2762 'f', 'o', 'o', 0x00,
2765 const unsigned char kV3FrameData
[] = {
2766 0x80, spdy_version_ch_
, 0x00, 0x08,
2767 0x00, 0x00, 0x00, 0x24,
2768 0x00, 0x00, 0x00, 0x01,
2769 0x00, 0x00, 0x00, 0x02,
2770 0x00, 0x00, 0x00, 0x03,
2771 'b', 'a', 'r', 0x00,
2772 0x00, 0x00, 0x03, 'f',
2773 'o', 'o', 0x00, 0x00,
2774 0x00, 0x03, 'f', 'o',
2775 'o', 0x00, 0x00, 0x00,
2778 const unsigned char kV4FrameData
[] = {
2779 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2780 0x04, 0x00, 0x00, 0x00, // Stream 1
2781 0x01, 0x00, 0x03, 0x62, // @.ba
2782 0x61, 0x72, 0x03, 0x66, // r.fo
2783 0x6f, 0x6f, 0x00, 0x03, // o@.f
2784 0x66, 0x6f, 0x6f, 0x03, // oo.b
2785 0x62, 0x61, 0x72, // ar
2787 SpdyHeadersIR
headers_ir(1);
2788 headers_ir
.SetHeader("bar", "foo");
2789 headers_ir
.SetHeader("foo", "bar");
2790 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2792 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2793 } else if (IsSpdy3()) {
2794 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2796 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2801 const char kDescription
[] =
2802 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2804 const unsigned char kV2FrameData
[] = {
2805 0x80, spdy_version_ch_
, 0x00, 0x08,
2806 0x01, 0x00, 0x00, 0x19,
2807 0x7f, 0xff, 0xff, 0xff,
2808 0x00, 0x00, 0x00, 0x02,
2809 0x00, 0x00, 0x00, 0x03,
2810 'f', 'o', 'o', 0x00,
2811 0x03, 'f', 'o', 'o',
2812 0x00, 0x03, 'b', 'a',
2815 const unsigned char kV3FrameData
[] = {
2816 0x80, spdy_version_ch_
, 0x00, 0x08,
2817 0x01, 0x00, 0x00, 0x21,
2818 0x7f, 0xff, 0xff, 0xff,
2819 0x00, 0x00, 0x00, 0x02,
2820 0x00, 0x00, 0x00, 0x00,
2821 0x00, 0x00, 0x00, 0x03,
2822 'f', 'o', 'o', 0x00,
2823 0x00, 0x00, 0x03, 'f',
2824 'o', 'o', 0x00, 0x00,
2825 0x00, 0x03, 'b', 'a',
2828 const unsigned char kV4FrameData
[] = {
2829 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2830 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2831 0xff, 0x00, 0x00, 0x03, // @..
2832 0x66, 0x6f, 0x6f, 0x00, // foo@
2833 0x03, 0x66, 0x6f, 0x6f, // .foo
2834 0x03, 0x62, 0x61, 0x72, // .bar
2836 SpdyHeadersIR
headers_ir(0x7fffffff);
2837 headers_ir
.set_fin(true);
2838 headers_ir
.SetHeader("", "foo");
2839 headers_ir
.SetHeader("foo", "bar");
2840 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2842 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2843 } else if (IsSpdy3()) {
2844 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2846 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2851 const char kDescription
[] =
2852 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2854 const unsigned char kV2FrameData
[] = {
2855 0x80, spdy_version_ch_
, 0x00, 0x08,
2856 0x01, 0x00, 0x00, 0x19,
2857 0x7f, 0xff, 0xff, 0xff,
2858 0x00, 0x00, 0x00, 0x02,
2859 0x00, 0x03, 'b', 'a',
2860 'r', 0x00, 0x03, 'f',
2861 'o', 'o', 0x00, 0x03,
2862 'f', 'o', 'o', 0x00,
2865 const unsigned char kV3FrameData
[] = {
2866 0x80, spdy_version_ch_
, 0x00, 0x08,
2867 0x01, 0x00, 0x00, 0x21,
2868 0x7f, 0xff, 0xff, 0xff,
2869 0x00, 0x00, 0x00, 0x02,
2870 0x00, 0x00, 0x00, 0x03,
2871 'b', 'a', 'r', 0x00,
2872 0x00, 0x00, 0x03, 'f',
2873 'o', 'o', 0x00, 0x00,
2874 0x00, 0x03, 'f', 'o',
2875 'o', 0x00, 0x00, 0x00,
2878 const unsigned char kV4FrameData
[] = {
2879 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2880 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2881 0xff, 0x00, 0x03, 0x62, // @.b
2882 0x61, 0x72, 0x03, 0x66, // ar.f
2883 0x6f, 0x6f, 0x00, 0x03, // oo@.
2884 0x66, 0x6f, 0x6f, 0x00, // foo.
2886 SpdyHeadersIR
headers_ir(0x7fffffff);
2887 headers_ir
.set_fin(true);
2888 headers_ir
.SetHeader("bar", "foo");
2889 headers_ir
.SetHeader("foo", "");
2890 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2892 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2893 } else if (IsSpdy3()) {
2894 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2896 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2901 const char kDescription
[] =
2902 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2904 const unsigned char kV4FrameData
[] = {
2905 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2906 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2907 0xff, 0x00, 0x00, 0x00, // parent stream
2908 0x00, 0xdb, // weight
2909 0x00, 0x03, 0x62, 0x61, // @.ba
2910 0x72, 0x03, 0x66, 0x6f, // r.fo
2911 0x6f, 0x00, 0x03, 0x66, // o@.f
2912 0x6f, 0x6f, 0x00, // oo.
2914 SpdyHeadersIR
headers_ir(0x7fffffff);
2915 headers_ir
.set_fin(true);
2916 headers_ir
.set_priority(1);
2917 headers_ir
.set_has_priority(true);
2918 headers_ir
.SetHeader("bar", "foo");
2919 headers_ir
.SetHeader("foo", "");
2920 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2921 if (IsSpdy2() || IsSpdy3()) {
2922 // HEADERS with priority not supported.
2924 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2929 const char kDescription
[] =
2930 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2932 const unsigned char kV4FrameData
[] = {
2933 0x00, 0x00, 0x15, 0x01, // Headers
2934 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2936 0xff, 0x05, 0x00, 0x00, // Pad length field
2937 0x03, 0x66, 0x6f, 0x6f, // .foo
2938 0x00, 0x03, 0x66, 0x6f, // @.fo
2939 0x6f, 0x03, 0x62, 0x61, // o.ba
2942 0x00, 0x00, 0x00, 0x00, 0x00,
2944 SpdyHeadersIR
headers_ir(0x7fffffff);
2945 headers_ir
.set_fin(true);
2946 headers_ir
.SetHeader("", "foo");
2947 headers_ir
.SetHeader("foo", "bar");
2948 headers_ir
.set_padding_len(6);
2949 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2950 if (IsSpdy2() || IsSpdy3()) {
2951 // Padding is not supported.
2953 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2958 // TODO(phajdan.jr): Clean up after we no longer need
2959 // to workaround http://crbug.com/139744.
2960 #if !defined(USE_SYSTEM_ZLIB)
2961 TEST_P(SpdyFramerTest
, CreateHeadersCompressed
) {
2962 SpdyFramer
framer(spdy_version_
);
2963 framer
.set_enable_compression(true);
2966 const char kDescription
[] = "HEADERS frame, no FIN";
2968 const unsigned char kV2FrameData
[] = {
2969 0x80, spdy_version_ch_
, 0x00, 0x08,
2970 0x00, 0x00, 0x00, 0x32,
2971 0x00, 0x00, 0x00, 0x01,
2972 0x00, 0x00, 0x38, 0xea,
2973 0xdf, 0xa2, 0x51, 0xb2,
2974 0x62, 0x60, 0x62, 0x60,
2975 0x4e, 0x4a, 0x2c, 0x62,
2976 0x60, 0x06, 0x08, 0xa0,
2977 0xb4, 0xfc, 0x7c, 0x80,
2978 0x00, 0x62, 0x60, 0x4e,
2979 0xcb, 0xcf, 0x67, 0x60,
2980 0x06, 0x08, 0xa0, 0xa4,
2981 0xc4, 0x22, 0x80, 0x00,
2982 0x02, 0x00, 0x00, 0x00,
2985 const unsigned char kV3FrameData
[] = {
2986 0x80, spdy_version_ch_
, 0x00, 0x08,
2987 0x00, 0x00, 0x00, 0x31,
2988 0x00, 0x00, 0x00, 0x01,
2989 0x38, 0xea, 0xe3, 0xc6,
2990 0xa7, 0xc2, 0x02, 0xe5,
2991 0x0e, 0x50, 0xc2, 0x4b,
2992 0x4a, 0x04, 0xe5, 0x0b,
2993 0x66, 0x80, 0x00, 0x4a,
2994 0xcb, 0xcf, 0x07, 0x08,
2995 0x20, 0x10, 0x95, 0x96,
2996 0x9f, 0x0f, 0xa2, 0x00,
2997 0x02, 0x28, 0x29, 0xb1,
2998 0x08, 0x20, 0x80, 0x00,
2999 0x00, 0x00, 0x00, 0xff,
3002 const unsigned char kV2SIMDFrameData
[] = {
3003 0x80, spdy_version_ch_
, 0x00, 0x08,
3004 0x00, 0x00, 0x00, 0x2f,
3005 0x00, 0x00, 0x00, 0x01,
3006 0x00, 0x00, 0x38, 0xea,
3007 0xdf, 0xa2, 0x51, 0xb2,
3008 0x62, 0x60, 0x62, 0x60,
3009 0x4e, 0x4a, 0x2c, 0x62,
3010 0x60, 0x06, 0x08, 0xa0,
3011 0xb4, 0xfc, 0x7c, 0x80,
3012 0x00, 0x62, 0x60, 0x06,
3013 0x13, 0x00, 0x01, 0x94,
3014 0x94, 0x58, 0x04, 0x10,
3015 0x40, 0x00, 0x00, 0x00,
3018 const unsigned char kV3SIMDFrameData
[] = {
3019 0x80, spdy_version_ch_
, 0x00, 0x08,
3020 0x00, 0x00, 0x00, 0x2c,
3021 0x00, 0x00, 0x00, 0x01,
3022 0x38, 0xea, 0xe3, 0xc6,
3023 0xa7, 0xc2, 0x02, 0xe5,
3024 0x0e, 0x50, 0xc2, 0x4b,
3025 0x4a, 0x04, 0xe5, 0x0b,
3026 0x66, 0x80, 0x00, 0x4a,
3027 0xcb, 0xcf, 0x07, 0x08,
3028 0x20, 0x24, 0x0a, 0x20,
3029 0x80, 0x92, 0x12, 0x8b,
3030 0x00, 0x02, 0x08, 0x00,
3031 0x00, 0x00, 0xff, 0xff,
3034 SpdyHeadersIR
headers_ir(1);
3035 headers_ir
.SetHeader("bar", "foo");
3036 headers_ir
.SetHeader("foo", "bar");
3037 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
3038 const unsigned char* frame_data
=
3039 reinterpret_cast<const unsigned char*>(frame
->data());
3041 // Try comparing with SIMD version, if that fails, do a failing check
3042 // with pretty printing against non-SIMD version
3043 if (memcmp(frame_data
,
3045 std::min(arraysize(kV2SIMDFrameData
), frame
->size())) != 0) {
3046 CompareCharArraysWithHexError(kDescription
,
3050 arraysize(kV2FrameData
));
3052 } else if (IsSpdy3()) {
3053 if (memcmp(frame_data
,
3055 std::min(arraysize(kV3SIMDFrameData
), frame
->size())) != 0) {
3056 CompareCharArraysWithHexError(kDescription
,
3060 arraysize(kV3FrameData
));
3063 // Deflate compression doesn't apply to HPACK.
3067 #endif // !defined(USE_SYSTEM_ZLIB)
3069 TEST_P(SpdyFramerTest
, CreateWindowUpdate
) {
3070 SpdyFramer
framer(spdy_version_
);
3073 const char kDescription
[] = "WINDOW_UPDATE frame";
3074 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3075 0x80, spdy_version_ch_
, 0x00, 0x09,
3076 0x00, 0x00, 0x00, 0x08,
3077 0x00, 0x00, 0x00, 0x01,
3078 0x00, 0x00, 0x00, 0x01,
3080 const unsigned char kV4FrameData
[] = {
3081 0x00, 0x00, 0x04, 0x08,
3082 0x00, 0x00, 0x00, 0x00,
3083 0x01, 0x00, 0x00, 0x00,
3086 scoped_ptr
<SpdyFrame
> frame(
3087 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3089 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
3091 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
3096 const char kDescription
[] = "WINDOW_UPDATE frame with max stream ID";
3097 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3098 0x80, spdy_version_ch_
, 0x00, 0x09,
3099 0x00, 0x00, 0x00, 0x08,
3100 0x7f, 0xff, 0xff, 0xff,
3101 0x00, 0x00, 0x00, 0x01,
3103 const unsigned char kV4FrameData
[] = {
3104 0x00, 0x00, 0x04, 0x08,
3105 0x00, 0x7f, 0xff, 0xff,
3106 0xff, 0x00, 0x00, 0x00,
3109 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
3110 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3112 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
3114 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
3119 const char kDescription
[] = "WINDOW_UPDATE frame with max window delta";
3120 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3121 0x80, spdy_version_ch_
, 0x00, 0x09,
3122 0x00, 0x00, 0x00, 0x08,
3123 0x00, 0x00, 0x00, 0x01,
3124 0x7f, 0xff, 0xff, 0xff,
3126 const unsigned char kV4FrameData
[] = {
3127 0x00, 0x00, 0x04, 0x08,
3128 0x00, 0x00, 0x00, 0x00,
3129 0x01, 0x7f, 0xff, 0xff,
3132 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
3133 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3135 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
3137 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
3142 TEST_P(SpdyFramerTest
, SerializeBlocked
) {
3143 if (spdy_version_
<= SPDY3
) {
3147 SpdyFramer
framer(spdy_version_
);
3149 const char kDescription
[] = "BLOCKED frame";
3150 const unsigned char kType
= static_cast<unsigned char>(
3151 SpdyConstants::SerializeFrameType(spdy_version_
, BLOCKED
));
3152 const unsigned char kFrameData
[] = {
3153 0x00, 0x00, 0x00, kType
, 0x00,
3154 0x00, 0x00, 0x00, 0x00,
3156 SpdyBlockedIR
blocked_ir(0);
3157 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
3158 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3161 TEST_P(SpdyFramerTest
, CreateBlocked
) {
3162 if (spdy_version_
<= SPDY3
) {
3166 SpdyFramer
framer(spdy_version_
);
3168 const char kDescription
[] = "BLOCKED frame";
3169 const SpdyStreamId kStreamId
= 3;
3171 scoped_ptr
<SpdySerializedFrame
> frame_serialized(
3172 framer
.SerializeBlocked(SpdyBlockedIR(kStreamId
)));
3173 SpdyBlockedIR
blocked_ir(kStreamId
);
3174 scoped_ptr
<SpdySerializedFrame
> frame_created(
3175 framer
.SerializeFrame(blocked_ir
));
3177 CompareFrames(kDescription
, *frame_serialized
, *frame_created
);
3180 TEST_P(SpdyFramerTest
, CreatePushPromiseUncompressed
) {
3181 if (spdy_version_
<= SPDY3
) {
3186 // Test framing PUSH_PROMISE without padding.
3187 SpdyFramer
framer(spdy_version_
);
3188 framer
.set_enable_compression(false);
3189 const char kDescription
[] = "PUSH_PROMISE frame without padding";
3191 const unsigned char kFrameData
[] = {
3192 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3193 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3194 0x2a, 0x00, 0x00, 0x00, // Stream 42
3195 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3196 0x61, 0x72, 0x03, 0x66, // ar.f
3197 0x6f, 0x6f, 0x00, 0x03, // oo@.
3198 0x66, 0x6f, 0x6f, 0x03, // foo.
3199 0x62, 0x61, 0x72, // bar
3202 SpdyPushPromiseIR
push_promise(42, 57);
3203 push_promise
.SetHeader("bar", "foo");
3204 push_promise
.SetHeader("foo", "bar");
3205 scoped_ptr
<SpdySerializedFrame
> frame(
3206 framer
.SerializePushPromise(push_promise
));
3207 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3211 // Test framing PUSH_PROMISE with one byte of padding.
3212 SpdyFramer
framer(spdy_version_
);
3213 framer
.set_enable_compression(false);
3214 const char kDescription
[] = "PUSH_PROMISE frame with one byte of padding";
3216 const unsigned char kFrameData
[] = {
3217 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3218 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3219 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3220 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3221 0x62, 0x61, 0x72, 0x03, // bar.
3222 0x66, 0x6f, 0x6f, 0x00, // foo@
3223 0x03, 0x66, 0x6f, 0x6f, // .foo
3224 0x03, 0x62, 0x61, 0x72, // .bar
3227 SpdyPushPromiseIR
push_promise(42, 57);
3228 push_promise
.set_padding_len(1);
3229 push_promise
.SetHeader("bar", "foo");
3230 push_promise
.SetHeader("foo", "bar");
3231 scoped_ptr
<SpdySerializedFrame
> frame(
3232 framer
.SerializePushPromise(push_promise
));
3233 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3237 // Test framing PUSH_PROMISE with 177 bytes of padding.
3238 SpdyFramer
framer(spdy_version_
);
3239 framer
.set_enable_compression(false);
3240 const char kDescription
[] = "PUSH_PROMISE frame with 177 bytes of padding";
3242 const unsigned char kFrameData
[] = {
3243 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3244 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3245 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3246 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3247 0x62, 0x61, 0x72, 0x03, // bar.
3248 0x66, 0x6f, 0x6f, 0x00, // foo@
3249 0x03, 0x66, 0x6f, 0x6f, // .foo
3250 0x03, 0x62, 0x61, 0x72, // .bar
3251 // Padding of 176 0x00(s).
3252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3269 SpdyPushPromiseIR
push_promise(42, 57);
3270 push_promise
.set_padding_len(177);
3271 push_promise
.SetHeader("bar", "foo");
3272 push_promise
.SetHeader("foo", "bar");
3273 scoped_ptr
<SpdySerializedFrame
> frame(
3274 framer
.SerializePushPromise(push_promise
));
3275 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3279 TEST_P(SpdyFramerTest
, GetNumberRequiredContinuationFrames
) {
3280 if (spdy_version_
<= SPDY3
) {
3284 SpdyFramer
framer(spdy_version_
);
3285 // Test case from https://crbug.com/464748.
3287 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer
, 2039));
3289 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer
, 2040));
3292 TEST_P(SpdyFramerTest
, CreateContinuationUncompressed
) {
3293 if (spdy_version_
<= SPDY3
) {
3297 SpdyFramer
framer(spdy_version_
);
3298 framer
.set_enable_compression(false);
3299 const char kDescription
[] = "CONTINUATION frame";
3301 const unsigned char kFrameData
[] = {
3302 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3303 0x04, 0x00, 0x00, 0x00, // end_headers = true
3304 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3305 0x61, 0x72, 0x03, 0x66, // ar.f
3306 0x6f, 0x6f, 0x00, 0x03, // oo@.
3307 0x66, 0x6f, 0x6f, 0x03, // foo.
3308 0x62, 0x61, 0x72, // bar
3311 SpdyContinuationIR
continuation(42);
3312 continuation
.SetHeader("bar", "foo");
3313 continuation
.SetHeader("foo", "bar");
3314 continuation
.set_end_headers(true);
3315 scoped_ptr
<SpdySerializedFrame
> frame(
3316 framer
.SerializeContinuation(continuation
));
3317 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3320 TEST_P(SpdyFramerTest
, CreatePushPromiseThenContinuationUncompressed
) {
3321 if (spdy_version_
<= SPDY3
) {
3326 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3327 // padding, cannot hold all the data payload, which is overflowed to the
3328 // consecutive CONTINUATION frame.
3329 SpdyFramer
framer(spdy_version_
);
3330 framer
.set_enable_compression(false);
3331 const char kDescription
[] =
3332 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3334 const unsigned char kPartialPushPromiseFrameData
[] = {
3335 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3336 0x08, 0x00, 0x00, 0x00, // PADDED
3337 0x2a, 0x00, 0x00, 0x00, // Stream 42
3338 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3339 0x78, 0x78, 0x78, 0x7f, // xxx.
3340 0x81, 0x07, 0x78, 0x78, // ..xx
3341 0x78, 0x78, 0x78, 0x78, // xxxx
3342 0x78, 0x78, 0x78, 0x78, // xxxx
3343 0x78, 0x78, 0x78, 0x78, // xxxx
3344 0x78, 0x78, 0x78, 0x78, // xxxx
3345 0x78, 0x78, 0x78, 0x78, // xxxx
3346 0x78, 0x78, 0x78, 0x78, // xxxx
3347 0x78, 0x78, 0x78, 0x78, // xxxx
3348 0x78, 0x78, 0x78, 0x78, // xxxx
3349 0x78, 0x78, 0x78, 0x78, // xxxx
3350 0x78, 0x78, 0x78, 0x78, // xxxx
3351 0x78, 0x78, 0x78, 0x78, // xxxx
3352 0x78, 0x78, 0x78, 0x78, // xxxx
3353 0x78, 0x78, 0x78, 0x78, // xxxx
3354 0x78, 0x78, 0x78, 0x78, // xxxx
3355 0x78, 0x78, 0x78, 0x78, // xxxx
3356 0x78, 0x78, 0x78, 0x78, // xxxx
3357 0x78, 0x78, 0x78, 0x78, // xxxx
3358 0x78, 0x78, 0x78, 0x78, // xxxx
3359 0x78, 0x78, 0x78, 0x78, // xxxx
3360 0x78, 0x78, 0x78, 0x78, // xxxx
3364 const unsigned char kContinuationFrameData
[] = {
3365 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3366 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3367 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3368 0x78, 0x78, 0x78, 0x78, // xxxx
3369 0x78, 0x78, 0x78, 0x78, // xxxx
3370 0x78, 0x78, 0x78, 0x78, // xxxx
3371 0x78, 0x78, 0x78, 0x78, // xxxx
3375 SpdyPushPromiseIR
push_promise(42, 57);
3376 push_promise
.set_padding_len(1);
3377 string
big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3378 push_promise
.SetHeader("xxx", big_value
);
3379 scoped_ptr
<SpdySerializedFrame
> frame(
3380 framer
.SerializePushPromise(push_promise
));
3382 // The entire frame should look like below:
3383 // Name Length in Byte
3384 // ------------------------------------------- Begin of PUSH_PROMISE frame
3385 // PUSH_PROMISE header 9
3386 // Pad length field 1
3387 // Promised stream 4
3388 // Length field of key 2
3390 // Length field of value 3
3391 // Part of big_value 16361
3392 // ------------------------------------------- Begin of CONTINUATION frame
3393 // CONTINUATION header 9
3394 // Remaining of big_value 22
3395 // ------------------------------------------- End
3397 // Length of everything listed above except big_value.
3398 int len_non_data_payload
= 31;
3400 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload
,
3403 // Partially compare the PUSH_PROMISE frame against the template.
3404 const unsigned char* frame_data
=
3405 reinterpret_cast<const unsigned char*>(frame
->data());
3406 CompareCharArraysWithHexError(kDescription
,
3408 arraysize(kPartialPushPromiseFrameData
),
3409 kPartialPushPromiseFrameData
,
3410 arraysize(kPartialPushPromiseFrameData
));
3412 // Compare the CONTINUATION frame against the template.
3413 frame_data
+= TestSpdyVisitor::sent_control_frame_max_size();
3414 CompareCharArraysWithHexError(kDescription
,
3416 arraysize(kContinuationFrameData
),
3417 kContinuationFrameData
,
3418 arraysize(kContinuationFrameData
));
3422 TEST_P(SpdyFramerTest
, CreateAltSvc
) {
3423 if (spdy_version_
<= SPDY3
) {
3427 SpdyFramer
framer(spdy_version_
);
3429 const char kDescription
[] = "ALTSVC frame";
3430 const char kType
= static_cast<unsigned char>(
3431 SpdyConstants::SerializeFrameType(spdy_version_
, ALTSVC
));
3432 const unsigned char kFrameData
[] = {
3433 0x00, 0x00, 0x1d, kType
, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
3434 0x06, 'o', 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd',
3435 '1', '=', '"', 'h', 'o', 's', 't', ':', '4', '4',
3436 '3', '"', ';', ' ', 'm', 'a', '=', '5',
3438 SpdyAltSvcIR
altsvc_ir(3);
3439 altsvc_ir
.set_max_age(5);
3440 altsvc_ir
.set_port(443);
3441 altsvc_ir
.set_protocol_id("pid1");
3442 altsvc_ir
.set_host("host");
3443 altsvc_ir
.set_origin("origin");
3444 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
3445 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3448 TEST_P(SpdyFramerTest
, CreatePriority
) {
3449 if (spdy_version_
<= SPDY3
) {
3453 SpdyFramer
framer(spdy_version_
);
3455 const char kDescription
[] = "PRIORITY frame";
3456 const unsigned char kType
= static_cast<unsigned char>(
3457 SpdyConstants::SerializeFrameType(spdy_version_
, PRIORITY
));
3458 const unsigned char kFrameData
[] = {
3459 0x00, 0x00, 0x05, kType
, 0x00,
3460 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3461 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3462 0x10, // Weight = 16
3464 SpdyPriorityIR
priority_ir(2, 1, 16, true);
3465 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(priority_ir
));
3466 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3467 SpdyPriorityIR
priority2(2);
3468 priority2
.set_parent_stream_id(1);
3469 priority2
.set_weight(16);
3470 priority2
.set_exclusive(true);
3471 frame
.reset(framer
.SerializeFrame(priority2
));
3472 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3475 TEST_P(SpdyFramerTest
, ReadCompressedSynStreamHeaderBlock
) {
3476 if (spdy_version_
> SPDY3
) {
3477 // SYN_STREAM not supported in SPDY>3
3480 SpdyFramer
framer(spdy_version_
);
3481 SpdySynStreamIR
syn_stream(1);
3482 syn_stream
.set_priority(1);
3483 syn_stream
.SetHeader("aa", "vv");
3484 syn_stream
.SetHeader("bb", "ww");
3485 SpdyHeaderBlock headers
= syn_stream
.name_value_block();
3486 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3487 EXPECT_TRUE(control_frame
.get() != NULL
);
3488 TestSpdyVisitor
visitor(spdy_version_
);
3489 visitor
.use_compression_
= true;
3490 visitor
.SimulateInFramer(
3491 reinterpret_cast<unsigned char*>(control_frame
->data()),
3492 control_frame
->size());
3493 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3494 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3497 TEST_P(SpdyFramerTest
, ReadCompressedSynReplyHeaderBlock
) {
3498 if (spdy_version_
> SPDY3
) {
3501 SpdyFramer
framer(spdy_version_
);
3502 SpdySynReplyIR
syn_reply(1);
3503 syn_reply
.SetHeader("alpha", "beta");
3504 syn_reply
.SetHeader("gamma", "delta");
3505 SpdyHeaderBlock headers
= syn_reply
.name_value_block();
3506 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynReply(syn_reply
));
3507 EXPECT_TRUE(control_frame
.get() != NULL
);
3508 TestSpdyVisitor
visitor(spdy_version_
);
3509 visitor
.use_compression_
= true;
3510 visitor
.SimulateInFramer(
3511 reinterpret_cast<unsigned char*>(control_frame
->data()),
3512 control_frame
->size());
3514 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
3515 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3517 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
3518 EXPECT_EQ(0, visitor
.headers_frame_count_
);
3520 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3523 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlock
) {
3524 SpdyFramer
framer(spdy_version_
);
3525 SpdyHeadersIR
headers_ir(1);
3526 headers_ir
.SetHeader("alpha", "beta");
3527 headers_ir
.SetHeader("gamma", "delta");
3528 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
3529 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
3530 EXPECT_TRUE(control_frame
.get() != NULL
);
3531 TestSpdyVisitor
visitor(spdy_version_
);
3532 visitor
.use_compression_
= true;
3533 visitor
.SimulateInFramer(
3534 reinterpret_cast<unsigned char*>(control_frame
->data()),
3535 control_frame
->size());
3536 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3537 // control_frame_header_data_count_ depends on the random sequence
3538 // produced by rand(), so adding, removing or running single tests
3539 // alters this value. The best we can do is assert that it happens
3541 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
3542 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3543 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3544 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3547 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlockWithHalfClose
) {
3548 SpdyFramer
framer(spdy_version_
);
3549 SpdyHeadersIR
headers_ir(1);
3550 headers_ir
.set_fin(true);
3551 headers_ir
.SetHeader("alpha", "beta");
3552 headers_ir
.SetHeader("gamma", "delta");
3553 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
3554 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
3555 EXPECT_TRUE(control_frame
.get() != NULL
);
3556 TestSpdyVisitor
visitor(spdy_version_
);
3557 visitor
.use_compression_
= true;
3558 visitor
.SimulateInFramer(
3559 reinterpret_cast<unsigned char*>(control_frame
->data()),
3560 control_frame
->size());
3561 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3562 // control_frame_header_data_count_ depends on the random sequence
3563 // produced by rand(), so adding, removing or running single tests
3564 // alters this value. The best we can do is assert that it happens
3566 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
3567 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3568 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
3569 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3572 TEST_P(SpdyFramerTest
, ControlFrameAtMaxSizeLimit
) {
3573 if (spdy_version_
> SPDY3
) {
3574 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3577 // First find the size of the header value in order to just reach the control
3579 SpdyFramer
framer(spdy_version_
);
3580 framer
.set_enable_compression(false);
3581 SpdySynStreamIR
syn_stream(1);
3582 syn_stream
.set_priority(1);
3583 syn_stream
.SetHeader("aa", "");
3584 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3585 const size_t kBigValueSize
=
3586 TestSpdyVisitor::sent_control_frame_max_size() - control_frame
->size();
3588 // Create a frame at exactly that size.
3589 string
big_value(kBigValueSize
, 'x');
3590 syn_stream
.SetHeader("aa", big_value
);
3591 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
3592 EXPECT_TRUE(control_frame
.get() != NULL
);
3593 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3594 control_frame
->size());
3596 TestSpdyVisitor
visitor(spdy_version_
);
3597 visitor
.SimulateInFramer(
3598 reinterpret_cast<unsigned char*>(control_frame
->data()),
3599 control_frame
->size());
3600 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3601 EXPECT_EQ(0, visitor
.error_count_
);
3602 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3603 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3604 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3605 EXPECT_LT(kBigValueSize
, visitor
.header_buffer_length_
);
3608 TEST_P(SpdyFramerTest
, ControlFrameMaximumSize
) {
3609 if (spdy_version_
> SPDY3
) {
3610 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3613 if (spdy_version_
< SPDY3
) {
3614 // Since SPDY/2 uses 16 bit header field lengths, one cannot easily create a
3615 // header frame of maximum size.
3618 // First find the size of the header value in order to just reach the control
3620 SpdyFramer
framer(spdy_version_
);
3621 framer
.set_enable_compression(false);
3622 SpdySynStreamIR
syn_stream(1);
3623 syn_stream
.SetHeader("aa", "");
3624 syn_stream
.set_priority(1);
3625 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3626 const size_t kBigValueSize
=
3627 SpdyConstants::GetFrameMaximumSize(spdy_version_
) - control_frame
->size();
3629 // Create a frame at exatly that size.
3630 string
big_value(kBigValueSize
, 'x');
3631 syn_stream
.SetHeader("aa", big_value
);
3632 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3633 // neither support that in Chromium, nor do we use the same DFATAL (see
3634 // SpdyFrameBuilder::WriteFramePrefix()).
3635 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
3637 EXPECT_TRUE(control_frame
.get() != NULL
);
3638 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_
),
3639 control_frame
->size());
3641 TestSpdyVisitor
visitor(spdy_version_
);
3642 visitor
.SimulateInFramer(
3643 reinterpret_cast<unsigned char*>(control_frame
->data()),
3644 control_frame
->size());
3645 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3646 EXPECT_EQ(0, visitor
.error_count_
);
3647 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3650 TEST_P(SpdyFramerTest
, TooLargeHeadersFrameUsesContinuation
) {
3651 if (spdy_version_
<= SPDY3
) {
3654 SpdyFramer
framer(spdy_version_
);
3655 framer
.set_enable_compression(false);
3656 SpdyHeadersIR
headers(1);
3657 headers
.set_padding_len(256);
3659 // Exact payload length will change with HPACK, but this should be long
3660 // enough to cause an overflow.
3661 const size_t kBigValueSize
= kControlFrameSizeLimit
;
3662 string
big_value(kBigValueSize
, 'x');
3663 headers
.SetHeader("aa", big_value
);
3664 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers
));
3665 EXPECT_TRUE(control_frame
.get() != NULL
);
3666 EXPECT_GT(control_frame
->size(),
3667 TestSpdyVisitor::sent_control_frame_max_size());
3669 TestSpdyVisitor
visitor(spdy_version_
);
3670 visitor
.SimulateInFramer(
3671 reinterpret_cast<unsigned char*>(control_frame
->data()),
3672 control_frame
->size());
3673 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3674 EXPECT_EQ(0, visitor
.error_count_
);
3675 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3676 EXPECT_EQ(16, visitor
.continuation_count_
);
3677 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3680 TEST_P(SpdyFramerTest
, TooLargePushPromiseFrameUsesContinuation
) {
3681 if (spdy_version_
<= SPDY3
) {
3684 SpdyFramer
framer(spdy_version_
);
3685 framer
.set_enable_compression(false);
3686 SpdyPushPromiseIR
push_promise(1, 2);
3687 push_promise
.set_padding_len(256);
3689 // Exact payload length will change with HPACK, but this should be long
3690 // enough to cause an overflow.
3691 const size_t kBigValueSize
= kControlFrameSizeLimit
;
3692 string
big_value(kBigValueSize
, 'x');
3693 push_promise
.SetHeader("aa", big_value
);
3694 scoped_ptr
<SpdyFrame
> control_frame(
3695 framer
.SerializePushPromise(push_promise
));
3696 EXPECT_TRUE(control_frame
.get() != NULL
);
3697 EXPECT_GT(control_frame
->size(),
3698 TestSpdyVisitor::sent_control_frame_max_size());
3700 TestSpdyVisitor
visitor(spdy_version_
);
3701 visitor
.SimulateInFramer(
3702 reinterpret_cast<unsigned char*>(control_frame
->data()),
3703 control_frame
->size());
3704 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3705 EXPECT_EQ(0, visitor
.error_count_
);
3706 EXPECT_EQ(1, visitor
.push_promise_frame_count_
);
3707 EXPECT_EQ(16, visitor
.continuation_count_
);
3708 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3711 // Check that the framer stops delivering header data chunks once the visitor
3712 // declares it doesn't want any more. This is important to guard against
3713 // "zip bomb" types of attacks.
3714 TEST_P(SpdyFramerTest
, ControlFrameMuchTooLarge
) {
3715 const size_t kHeaderBufferChunks
= 4;
3716 const size_t kHeaderBufferSize
=
3717 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks
;
3718 const size_t kBigValueSize
= kHeaderBufferSize
* 2;
3719 string
big_value(kBigValueSize
, 'x');
3720 SpdyFramer
framer(spdy_version_
);
3721 SpdyHeadersIR
headers(1);
3722 headers
.set_priority(1);
3723 headers
.set_fin(true);
3724 headers
.SetHeader("aa", big_value
);
3725 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers
));
3726 EXPECT_TRUE(control_frame
.get() != NULL
);
3727 TestSpdyVisitor
visitor(spdy_version_
);
3728 visitor
.set_header_buffer_size(kHeaderBufferSize
);
3729 visitor
.use_compression_
= true;
3730 visitor
.SimulateInFramer(
3731 reinterpret_cast<unsigned char*>(control_frame
->data()),
3732 control_frame
->size());
3733 EXPECT_FALSE(visitor
.header_buffer_valid_
);
3734 EXPECT_EQ(1, visitor
.error_count_
);
3735 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
3736 visitor
.framer_
.error_code())
3737 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3739 // The framer should have stoped delivering chunks after the visitor
3740 // signaled "stop" by returning false from OnControlFrameHeaderData().
3742 // control_frame_header_data_count_ depends on the random sequence
3743 // produced by rand(), so adding, removing or running single tests
3744 // alters this value. The best we can do is assert that it happens
3745 // at least kHeaderBufferChunks + 1.
3746 EXPECT_LE(kHeaderBufferChunks
+ 1,
3747 static_cast<unsigned>(visitor
.control_frame_header_data_count_
));
3748 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
3750 // The framer should not have sent half-close to the visitor.
3751 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3754 TEST_P(SpdyFramerTest
, DecompressCorruptHeaderBlock
) {
3755 if (spdy_version_
> SPDY3
) {
3756 // Deflate compression doesn't apply to HPACK.
3759 SpdyFramer
framer(spdy_version_
);
3760 framer
.set_enable_compression(false);
3761 // Construct a SYN_STREAM control frame without compressing the header block,
3762 // and have the framer try to decompress it. This will cause the framer to
3763 // deal with a decompression error.
3764 SpdySynStreamIR
syn_stream(1);
3765 syn_stream
.set_priority(1);
3766 syn_stream
.SetHeader("aa", "alpha beta gamma delta");
3767 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3768 TestSpdyVisitor
visitor(spdy_version_
);
3769 visitor
.use_compression_
= true;
3770 visitor
.SimulateInFramer(
3771 reinterpret_cast<unsigned char*>(control_frame
->data()),
3772 control_frame
->size());
3773 EXPECT_EQ(1, visitor
.error_count_
);
3774 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE
, visitor
.framer_
.error_code())
3775 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3776 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3779 TEST_P(SpdyFramerTest
, ControlFrameSizesAreValidated
) {
3780 SpdyFramer
framer(spdy_version_
);
3781 // Create a GoAway frame that has a few extra bytes at the end.
3782 // We create enough overhead to overflow the framer's control frame buffer.
3783 ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
3784 const size_t length
= SpdyFramerPeer::ControlFrameBufferSize() + 1;
3785 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3786 0x80, spdy_version_ch_
, 0x00, 0x07,
3787 0x00, 0x00, 0x00, static_cast<unsigned char>(length
),
3788 0x00, 0x00, 0x00, 0x00, // Stream ID
3789 0x00, 0x00, 0x00, 0x00, // Status
3792 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3793 // since it may carry opaque data. Verify that minimal length is tested.
3794 ASSERT_GT(framer
.GetGoAwayMinimumSize(), framer
.GetControlFrameHeaderSize());
3795 const size_t less_than_min_length
=
3796 framer
.GetGoAwayMinimumSize() - framer
.GetControlFrameHeaderSize() - 1;
3797 ASSERT_LE(less_than_min_length
, std::numeric_limits
<unsigned char>::max());
3798 const unsigned char kV4FrameData
[] = {
3799 0x00, 0x00, static_cast<unsigned char>(less_than_min_length
), 0x07,
3800 0x00, 0x00, 0x00, 0x00,
3801 0x00, 0x00, 0x00, 0x00, // Stream Id
3802 0x00, 0x00, 0x00, 0x00, // Status
3805 const size_t pad_length
=
3806 length
+ framer
.GetControlFrameHeaderSize() -
3807 (IsSpdy4() ? sizeof(kV4FrameData
) : sizeof(kV3FrameData
));
3808 string
pad(pad_length
, 'A');
3809 TestSpdyVisitor
visitor(spdy_version_
);
3812 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3814 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3816 visitor
.SimulateInFramer(
3817 reinterpret_cast<const unsigned char*>(pad
.c_str()),
3820 EXPECT_EQ(1, visitor
.error_count_
); // This generated an error.
3821 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
3822 visitor
.framer_
.error_code())
3823 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3824 EXPECT_EQ(0, visitor
.goaway_count_
); // Frame not parsed.
3827 TEST_P(SpdyFramerTest
, ReadZeroLenSettingsFrame
) {
3828 SpdyFramer
framer(spdy_version_
);
3829 SpdySettingsIR settings_ir
;
3830 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3831 SetFrameLength(control_frame
.get(), 0, spdy_version_
);
3832 TestSpdyVisitor
visitor(spdy_version_
);
3833 visitor
.use_compression_
= false;
3834 visitor
.SimulateInFramer(
3835 reinterpret_cast<unsigned char*>(control_frame
->data()),
3836 framer
.GetControlFrameHeaderSize());
3837 if (spdy_version_
<= SPDY3
) {
3838 // Should generate an error, since zero-len settings frames are unsupported.
3839 EXPECT_EQ(1, visitor
.error_count_
);
3841 // Zero-len settings frames are permitted as of SPDY 4.
3842 EXPECT_EQ(0, visitor
.error_count_
);
3846 // Tests handling of SETTINGS frames with invalid length.
3847 TEST_P(SpdyFramerTest
, ReadBogusLenSettingsFrame
) {
3848 SpdyFramer
framer(spdy_version_
);
3849 SpdySettingsIR settings_ir
;
3851 // Add a setting to pad the frame so that we don't get a buffer overflow when
3852 // calling SimulateInFramer() below.
3853 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
,
3857 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3858 const size_t kNewLength
= 14;
3859 SetFrameLength(control_frame
.get(), kNewLength
, spdy_version_
);
3860 TestSpdyVisitor
visitor(spdy_version_
);
3861 visitor
.use_compression_
= false;
3862 visitor
.SimulateInFramer(
3863 reinterpret_cast<unsigned char*>(control_frame
->data()),
3864 framer
.GetControlFrameHeaderSize() + kNewLength
);
3865 // Should generate an error, since its not possible to have a
3866 // settings frame of length kNewLength.
3867 EXPECT_EQ(1, visitor
.error_count_
);
3870 // Tests handling of SETTINGS frames larger than the frame buffer size.
3871 TEST_P(SpdyFramerTest
, ReadLargeSettingsFrame
) {
3872 SpdyFramer
framer(spdy_version_
);
3873 SpdySettingsIR settings_ir
;
3874 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
3878 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 2),
3882 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 3),
3887 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3888 EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame
->size());
3889 TestSpdyVisitor
visitor(spdy_version_
);
3890 visitor
.use_compression_
= false;
3892 // Read all at once.
3893 visitor
.SimulateInFramer(
3894 reinterpret_cast<unsigned char*>(control_frame
->data()),
3895 control_frame
->size());
3896 EXPECT_EQ(0, visitor
.error_count_
);
3897 EXPECT_EQ(3, visitor
.setting_count_
);
3898 if (spdy_version_
> SPDY3
) {
3899 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3902 // Read data in small chunks.
3903 size_t framed_data
= 0;
3904 size_t unframed_data
= control_frame
->size();
3905 size_t kReadChunkSize
= 5; // Read five bytes at a time.
3906 while (unframed_data
> 0) {
3907 size_t to_read
= std::min(kReadChunkSize
, unframed_data
);
3908 visitor
.SimulateInFramer(
3909 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
3911 unframed_data
-= to_read
;
3912 framed_data
+= to_read
;
3914 EXPECT_EQ(0, visitor
.error_count_
);
3915 EXPECT_EQ(3 * 2, visitor
.setting_count_
);
3916 if (spdy_version_
> SPDY3
) {
3917 EXPECT_EQ(2, visitor
.settings_ack_sent_
);
3921 // Tests handling of SETTINGS frame with duplicate entries.
3922 TEST_P(SpdyFramerTest
, ReadDuplicateSettings
) {
3923 SpdyFramer
framer(spdy_version_
);
3925 const unsigned char kV2FrameData
[] = {
3926 0x80, spdy_version_ch_
, 0x00, 0x04,
3927 0x00, 0x00, 0x00, 0x1C,
3928 0x00, 0x00, 0x00, 0x03,
3929 0x01, 0x00, 0x00, 0x00, // 1st Setting
3930 0x00, 0x00, 0x00, 0x02,
3931 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3932 0x00, 0x00, 0x00, 0x03,
3933 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3934 0x00, 0x00, 0x00, 0x03,
3936 const unsigned char kV3FrameData
[] = {
3937 0x80, spdy_version_ch_
, 0x00, 0x04,
3938 0x00, 0x00, 0x00, 0x1C,
3939 0x00, 0x00, 0x00, 0x03,
3940 0x00, 0x00, 0x00, 0x01, // 1st Setting
3941 0x00, 0x00, 0x00, 0x02,
3942 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3943 0x00, 0x00, 0x00, 0x03,
3944 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3945 0x00, 0x00, 0x00, 0x03,
3947 const unsigned char kV4FrameData
[] = {
3948 0x00, 0x00, 0x12, 0x04,
3949 0x00, 0x00, 0x00, 0x00,
3950 0x00, 0x00, 0x01, // 1st Setting
3951 0x00, 0x00, 0x00, 0x02,
3952 0x00, 0x01, // 2nd (duplicate) Setting
3953 0x00, 0x00, 0x00, 0x03,
3954 0x00, 0x03, // 3rd (unprocessed) Setting
3955 0x00, 0x00, 0x00, 0x03,
3958 TestSpdyVisitor
visitor(spdy_version_
);
3959 visitor
.use_compression_
= false;
3961 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
3962 } else if (IsSpdy3()) {
3963 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3965 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3969 EXPECT_EQ(1, visitor
.setting_count_
);
3970 EXPECT_EQ(1, visitor
.error_count_
);
3972 // In SPDY 4+, duplicate settings are allowed;
3973 // each setting replaces the previous value for that setting.
3974 EXPECT_EQ(3, visitor
.setting_count_
);
3975 EXPECT_EQ(0, visitor
.error_count_
);
3976 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3980 // Tests handling of SETTINGS frame with a setting we don't recognize.
3981 TEST_P(SpdyFramerTest
, ReadUnknownSettingsId
) {
3982 SpdyFramer
framer(spdy_version_
);
3984 const unsigned char kV2FrameData
[] = {
3985 0x80, spdy_version_ch_
, 0x00, 0x04,
3986 0x00, 0x00, 0x00, 0x1C,
3987 0x00, 0x00, 0x00, 0x01,
3988 0x10, 0x00, 0x00, 0x00, // 1st Setting
3989 0x00, 0x00, 0x00, 0x02,
3991 const unsigned char kV3FrameData
[] = {
3992 0x80, spdy_version_ch_
, 0x00, 0x04,
3993 0x00, 0x00, 0x00, 0x1C,
3994 0x00, 0x00, 0x00, 0x01,
3995 0x00, 0x00, 0x00, 0x10, // 1st Setting
3996 0x00, 0x00, 0x00, 0x02,
3998 const unsigned char kV4FrameData
[] = {
3999 0x00, 0x00, 0x06, 0x04,
4000 0x00, 0x00, 0x00, 0x00,
4001 0x00, 0x00, 0x10, // 1st Setting
4002 0x00, 0x00, 0x00, 0x02,
4005 TestSpdyVisitor
visitor(spdy_version_
);
4006 visitor
.use_compression_
= false;
4008 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
4009 } else if (IsSpdy3()) {
4010 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
4012 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
4016 EXPECT_EQ(0, visitor
.setting_count_
);
4017 EXPECT_EQ(1, visitor
.error_count_
);
4019 // In SPDY 4+, we ignore unknown settings because of extensions.
4020 EXPECT_EQ(0, visitor
.setting_count_
);
4021 EXPECT_EQ(0, visitor
.error_count_
);
4025 // Tests handling of SETTINGS frame with entries out of order.
4026 TEST_P(SpdyFramerTest
, ReadOutOfOrderSettings
) {
4027 SpdyFramer
framer(spdy_version_
);
4029 const unsigned char kV2FrameData
[] = {
4030 0x80, spdy_version_ch_
, 0x00, 0x04,
4031 0x00, 0x00, 0x00, 0x1C,
4032 0x00, 0x00, 0x00, 0x03,
4033 0x02, 0x00, 0x00, 0x00, // 1st Setting
4034 0x00, 0x00, 0x00, 0x02,
4035 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4036 0x00, 0x00, 0x00, 0x03,
4037 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4038 0x00, 0x00, 0x00, 0x03,
4040 const unsigned char kV3FrameData
[] = {
4041 0x80, spdy_version_ch_
, 0x00, 0x04,
4042 0x00, 0x00, 0x00, 0x1C,
4043 0x00, 0x00, 0x00, 0x03,
4044 0x00, 0x00, 0x00, 0x02, // 1st Setting
4045 0x00, 0x00, 0x00, 0x02,
4046 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4047 0x00, 0x00, 0x00, 0x03,
4048 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4049 0x00, 0x00, 0x00, 0x03,
4051 const unsigned char kV4FrameData
[] = {
4052 0x00, 0x00, 0x12, 0x04,
4053 0x00, 0x00, 0x00, 0x00,
4054 0x00, 0x00, 0x02, // 1st Setting
4055 0x00, 0x00, 0x00, 0x02,
4056 0x00, 0x01, // 2nd (out of order) Setting
4057 0x00, 0x00, 0x00, 0x03,
4058 0x00, 0x03, // 3rd (unprocessed) Setting
4059 0x00, 0x00, 0x00, 0x03,
4062 TestSpdyVisitor
visitor(spdy_version_
);
4063 visitor
.use_compression_
= false;
4065 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
4066 } else if (IsSpdy3()) {
4067 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
4069 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
4073 EXPECT_EQ(1, visitor
.setting_count_
);
4074 EXPECT_EQ(1, visitor
.error_count_
);
4076 // In SPDY 4+, settings are allowed in any order.
4077 EXPECT_EQ(3, visitor
.setting_count_
);
4078 EXPECT_EQ(0, visitor
.error_count_
);
4082 TEST_P(SpdyFramerTest
, ProcessSettingsAckFrame
) {
4083 if (spdy_version_
<= SPDY3
) {
4086 SpdyFramer
framer(spdy_version_
);
4088 const unsigned char kFrameData
[] = {
4089 0x00, 0x00, 0x00, 0x04, 0x01,
4090 0x00, 0x00, 0x00, 0x00,
4093 TestSpdyVisitor
visitor(spdy_version_
);
4094 visitor
.use_compression_
= false;
4095 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
4097 EXPECT_EQ(0, visitor
.error_count_
);
4098 EXPECT_EQ(0, visitor
.setting_count_
);
4099 EXPECT_EQ(1, visitor
.settings_ack_received_
);
4102 TEST_P(SpdyFramerTest
, ProcessDataFrameWithPadding
) {
4103 if (spdy_version_
<= SPDY3
) {
4107 const int kPaddingLen
= 119;
4108 const char data_payload
[] = "hello";
4110 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4111 SpdyFramer
framer(spdy_version_
);
4112 framer
.set_visitor(&visitor
);
4114 SpdyDataIR
data_ir(1, data_payload
);
4115 data_ir
.set_padding_len(kPaddingLen
);
4116 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4117 ASSERT_TRUE(frame
.get() != NULL
);
4119 int bytes_consumed
= 0;
4121 // Send the frame header.
4122 EXPECT_CALL(visitor
, OnDataFrameHeader(1,
4123 kPaddingLen
+ strlen(data_payload
),
4125 CHECK_EQ(framer
.GetDataFrameMinimumSize(),
4126 framer
.ProcessInput(frame
->data(),
4127 framer
.GetDataFrameMinimumSize()));
4128 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH
);
4129 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4130 bytes_consumed
+= framer
.GetDataFrameMinimumSize();
4132 // Send the padding length field.
4133 EXPECT_CALL(visitor
, OnStreamPadding(1, 1));
4134 CHECK_EQ(1u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 1));
4135 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME
);
4136 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4137 bytes_consumed
+= 1;
4139 // Send the first two bytes of the data payload, i.e., "he".
4140 EXPECT_CALL(visitor
, OnStreamFrameData(1, _
, 2, false));
4141 CHECK_EQ(2u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 2));
4142 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME
);
4143 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4144 bytes_consumed
+= 2;
4146 // Send the rest three bytes of the data payload, i.e., "llo".
4147 EXPECT_CALL(visitor
, OnStreamFrameData(1, _
, 3, false));
4148 CHECK_EQ(3u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 3));
4149 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_CONSUME_PADDING
);
4150 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4151 bytes_consumed
+= 3;
4153 // Send the first 100 bytes of the padding payload.
4154 EXPECT_CALL(visitor
, OnStreamPadding(1, 100));
4155 CHECK_EQ(100u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 100));
4156 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_CONSUME_PADDING
);
4157 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4158 bytes_consumed
+= 100;
4160 // Send rest of the padding payload.
4161 EXPECT_CALL(visitor
, OnStreamPadding(1, 18));
4162 CHECK_EQ(18u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 18));
4163 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_RESET
);
4164 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4167 TEST_P(SpdyFramerTest
, ReadWindowUpdate
) {
4168 SpdyFramer
framer(spdy_version_
);
4169 scoped_ptr
<SpdyFrame
> control_frame(
4170 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4171 TestSpdyVisitor
visitor(spdy_version_
);
4172 visitor
.SimulateInFramer(
4173 reinterpret_cast<unsigned char*>(control_frame
->data()),
4174 control_frame
->size());
4175 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
4176 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
4179 TEST_P(SpdyFramerTest
, ReceiveCredentialFrame
) {
4183 SpdyFramer
framer(spdy_version_
);
4184 const unsigned char kV3FrameData
[] = { // Also applies for V2.
4185 0x80, spdy_version_ch_
, 0x00, 0x0A,
4186 0x00, 0x00, 0x00, 0x33,
4187 0x00, 0x03, 0x00, 0x00,
4188 0x00, 0x05, 'p', 'r',
4189 'o', 'o', 'f', 0x00,
4190 0x00, 0x00, 0x06, 'a',
4192 't', 0x00, 0x00, 0x00,
4193 0x0C, 'a', 'n', 'o',
4196 't', 0x00, 0x00, 0x00,
4197 0x0A, 'f', 'i', 'n',
4201 TestSpdyVisitor
visitor(spdy_version_
);
4202 visitor
.use_compression_
= false;
4203 visitor
.SimulateInFramer(kV3FrameData
, arraysize(kV3FrameData
));
4204 EXPECT_EQ(0, visitor
.error_count_
);
4207 TEST_P(SpdyFramerTest
, ReadCredentialFrameFollowedByAnotherFrame
) {
4211 SpdyFramer
framer(spdy_version_
);
4212 const unsigned char kV3FrameData
[] = { // Also applies for V2.
4213 0x80, spdy_version_ch_
, 0x00, 0x0A,
4214 0x00, 0x00, 0x00, 0x33,
4215 0x00, 0x03, 0x00, 0x00,
4216 0x00, 0x05, 'p', 'r',
4217 'o', 'o', 'f', 0x00,
4218 0x00, 0x00, 0x06, 'a',
4220 't', 0x00, 0x00, 0x00,
4221 0x0C, 'a', 'n', 'o',
4224 't', 0x00, 0x00, 0x00,
4225 0x0A, 'f', 'i', 'n',
4229 TestSpdyVisitor
visitor(spdy_version_
);
4230 visitor
.use_compression_
= false;
4231 string
multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData
),
4232 arraysize(kV3FrameData
));
4233 scoped_ptr
<SpdyFrame
> control_frame(
4234 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4235 multiple_frame_data
.append(string(control_frame
->data(),
4236 control_frame
->size()));
4237 visitor
.SimulateInFramer(
4238 reinterpret_cast<unsigned const char*>(multiple_frame_data
.data()),
4239 multiple_frame_data
.length());
4240 EXPECT_EQ(0, visitor
.error_count_
);
4241 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
4242 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
4245 TEST_P(SpdyFramerTest
, ReadCompressedPushPromise
) {
4246 if (spdy_version_
<= SPDY3
) {
4250 SpdyFramer
framer(spdy_version_
);
4251 SpdyPushPromiseIR
push_promise(42, 57);
4252 push_promise
.SetHeader("foo", "bar");
4253 push_promise
.SetHeader("bar", "foofoo");
4254 SpdyHeaderBlock headers
= push_promise
.name_value_block();
4255 scoped_ptr
<SpdySerializedFrame
> frame(
4256 framer
.SerializePushPromise(push_promise
));
4257 EXPECT_TRUE(frame
.get() != NULL
);
4258 TestSpdyVisitor
visitor(spdy_version_
);
4259 visitor
.use_compression_
= true;
4260 visitor
.SimulateInFramer(
4261 reinterpret_cast<unsigned char*>(frame
->data()),
4263 EXPECT_EQ(42u, visitor
.last_push_promise_stream_
);
4264 EXPECT_EQ(57u, visitor
.last_push_promise_promised_stream_
);
4265 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
4268 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuation
) {
4269 if (spdy_version_
<= SPDY3
) {
4273 const unsigned char kInput
[] = {
4274 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4275 0x00, 0x00, 0x00, 0x01, // Stream 1
4276 0x03, // Padding of 3.
4277 0x00, 0x06, 0x63, 0x6f,
4278 0x6f, 0x6b, 0x69, 0x65,
4279 0x07, 0x66, 0x6f, 0x6f,
4280 0x3d, 0x62, 0x61, 0x72,
4283 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4284 0x00, 0x00, 0x00, 0x01, // Stream 1
4285 0x00, 0x06, 0x63, 0x6f,
4286 0x6f, 0x6b, 0x69, 0x65,
4287 0x08, 0x62, 0x61, 0x7a,
4288 0x3d, 0x62, 0x69, 0x6e,
4289 0x67, 0x00, 0x06, 0x63,
4291 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4292 0x00, 0x00, 0x00, 0x01, // Stream 1
4293 0x6f, 0x6f, 0x6b, 0x69,
4294 0x65, 0x00, 0x00, 0x04,
4295 0x6e, 0x61, 0x6d, 0x65,
4296 0x05, 0x76, 0x61, 0x6c,
4300 TestSpdyVisitor
visitor(spdy_version_
);
4301 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4303 EXPECT_EQ(0, visitor
.error_count_
);
4304 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4305 EXPECT_EQ(2, visitor
.continuation_count_
);
4306 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4307 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
4309 EXPECT_THAT(visitor
.headers_
,
4310 testing::ElementsAre(
4311 testing::Pair("cookie", "foo=bar; baz=bing; "),
4312 testing::Pair("name", "value")));
4315 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuationAndFin
) {
4316 if (spdy_version_
<= SPDY3
) {
4320 const unsigned char kInput
[] = {
4321 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4322 0x00, 0x00, 0x00, 0x01, // Stream 1
4323 0x00, 0x06, 0x63, 0x6f,
4324 0x6f, 0x6b, 0x69, 0x65,
4325 0x07, 0x66, 0x6f, 0x6f,
4326 0x3d, 0x62, 0x61, 0x72,
4328 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4329 0x00, 0x00, 0x00, 0x01, // Stream 1
4330 0x00, 0x06, 0x63, 0x6f,
4331 0x6f, 0x6b, 0x69, 0x65,
4332 0x08, 0x62, 0x61, 0x7a,
4333 0x3d, 0x62, 0x69, 0x6e,
4334 0x67, 0x00, 0x06, 0x63,
4336 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4337 0x00, 0x00, 0x00, 0x01, // Stream 1
4338 0x6f, 0x6f, 0x6b, 0x69,
4339 0x65, 0x00, 0x00, 0x04,
4340 0x6e, 0x61, 0x6d, 0x65,
4341 0x05, 0x76, 0x61, 0x6c,
4345 SpdyFramer
framer(spdy_version_
);
4346 TestSpdyVisitor
visitor(spdy_version_
);
4347 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4349 EXPECT_EQ(0, visitor
.error_count_
);
4350 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4351 EXPECT_EQ(2, visitor
.continuation_count_
);
4352 EXPECT_EQ(1, visitor
.fin_flag_count_
);
4353 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4354 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
4356 EXPECT_THAT(visitor
.headers_
,
4357 testing::ElementsAre(
4358 testing::Pair("cookie", "foo=bar; baz=bing; "),
4359 testing::Pair("name", "value")));
4362 TEST_P(SpdyFramerTest
, ReadPushPromiseWithContinuation
) {
4363 if (spdy_version_
<= SPDY3
) {
4367 const unsigned char kInput
[] = {
4368 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4369 0x08, 0x00, 0x00, 0x00, // PADDED
4370 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4371 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4372 0x63, 0x6f, 0x6f, 0x6b,
4373 0x69, 0x65, 0x07, 0x66,
4374 0x6f, 0x6f, 0x3d, 0x62,
4375 0x61, 0x72, 0x00, 0x00,
4377 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4378 0x00, 0x00, 0x00, 0x00,
4379 0x01, 0x00, 0x06, 0x63, // Stream 1
4380 0x6f, 0x6f, 0x6b, 0x69,
4381 0x65, 0x08, 0x62, 0x61,
4382 0x7a, 0x3d, 0x62, 0x69,
4383 0x6e, 0x67, 0x00, 0x06,
4386 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4387 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4388 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4389 0x69, 0x65, 0x00, 0x00,
4390 0x04, 0x6e, 0x61, 0x6d,
4391 0x65, 0x05, 0x76, 0x61,
4395 SpdyFramer
framer(spdy_version_
);
4396 TestSpdyVisitor
visitor(spdy_version_
);
4397 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4399 EXPECT_EQ(0, visitor
.error_count_
);
4400 EXPECT_EQ(1u, visitor
.last_push_promise_stream_
);
4401 EXPECT_EQ(42u, visitor
.last_push_promise_promised_stream_
);
4402 EXPECT_EQ(2, visitor
.continuation_count_
);
4403 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4404 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
4406 EXPECT_THAT(visitor
.headers_
,
4407 testing::ElementsAre(
4408 testing::Pair("cookie", "foo=bar; baz=bing; "),
4409 testing::Pair("name", "value")));
4412 TEST_P(SpdyFramerTest
, ReadContinuationWithWrongStreamId
) {
4413 if (spdy_version_
<= SPDY3
) {
4417 const unsigned char kInput
[] = {
4418 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4419 0x00, 0x00, 0x00, 0x01, // Stream 1
4420 0x00, 0x06, 0x63, 0x6f,
4421 0x6f, 0x6b, 0x69, 0x65,
4422 0x07, 0x66, 0x6f, 0x6f,
4423 0x3d, 0x62, 0x61, 0x72,
4425 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4426 0x00, 0x00, 0x00, 0x02, // Stream 2
4427 0x00, 0x06, 0x63, 0x6f,
4428 0x6f, 0x6b, 0x69, 0x65,
4429 0x08, 0x62, 0x61, 0x7a,
4430 0x3d, 0x62, 0x69, 0x6e,
4431 0x67, 0x00, 0x06, 0x63,
4434 SpdyFramer
framer(spdy_version_
);
4435 TestSpdyVisitor
visitor(spdy_version_
);
4436 framer
.set_visitor(&visitor
);
4437 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4439 EXPECT_EQ(1, visitor
.error_count_
);
4440 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
4441 visitor
.framer_
.error_code())
4442 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4443 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4444 EXPECT_EQ(0, visitor
.continuation_count_
);
4445 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4448 TEST_P(SpdyFramerTest
, ReadContinuationOutOfOrder
) {
4449 if (spdy_version_
<= SPDY3
) {
4453 const unsigned char kInput
[] = {
4454 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4455 0x00, 0x00, 0x00, 0x01, // Stream 1
4456 0x00, 0x06, 0x63, 0x6f,
4457 0x6f, 0x6b, 0x69, 0x65,
4458 0x07, 0x66, 0x6f, 0x6f,
4459 0x3d, 0x62, 0x61, 0x72,
4462 SpdyFramer
framer(spdy_version_
);
4463 TestSpdyVisitor
visitor(spdy_version_
);
4464 framer
.set_visitor(&visitor
);
4465 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4467 EXPECT_EQ(1, visitor
.error_count_
);
4468 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4469 visitor
.framer_
.error_code())
4470 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4471 EXPECT_EQ(0, visitor
.continuation_count_
);
4472 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4475 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveData
) {
4476 if (spdy_version_
<= SPDY3
) {
4480 const unsigned char kInput
[] = {
4481 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4482 0x00, 0x00, 0x00, 0x01, // Stream 1
4483 0x00, 0x06, 0x63, 0x6f,
4484 0x6f, 0x6b, 0x69, 0x65,
4485 0x07, 0x66, 0x6f, 0x6f,
4486 0x3d, 0x62, 0x61, 0x72,
4488 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4489 0x00, 0x00, 0x00, 0x04,
4490 0xde, 0xad, 0xbe, 0xef,
4493 SpdyFramer
framer(spdy_version_
);
4494 TestSpdyVisitor
visitor(spdy_version_
);
4495 framer
.set_visitor(&visitor
);
4496 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4498 EXPECT_EQ(1, visitor
.error_count_
);
4499 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4500 visitor
.framer_
.error_code())
4501 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4502 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4503 EXPECT_EQ(0, visitor
.continuation_count_
);
4504 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4505 EXPECT_EQ(0, visitor
.data_frame_count_
);
4508 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveControlFrame
) {
4509 if (spdy_version_
<= SPDY3
) {
4513 const unsigned char kInput
[] = {
4514 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4515 0x00, 0x00, 0x00, 0x01, // Stream 1
4516 0x00, 0x06, 0x63, 0x6f,
4517 0x6f, 0x6b, 0x69, 0x65,
4518 0x07, 0x66, 0x6f, 0x6f,
4519 0x3d, 0x62, 0x61, 0x72,
4521 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4522 0x00, 0x00, 0x00, 0x01, // Stream 1
4523 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4524 0x6f, 0x6b, 0x69, 0x65,
4525 0x08, 0x62, 0x61, 0x7a,
4526 0x3d, 0x62, 0x69, 0x6e,
4527 0x67, 0x00, 0x06, 0x63,
4530 SpdyFramer
framer(spdy_version_
);
4531 TestSpdyVisitor
visitor(spdy_version_
);
4532 framer
.set_visitor(&visitor
);
4533 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4535 EXPECT_EQ(1, visitor
.error_count_
);
4536 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4537 visitor
.framer_
.error_code())
4538 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4539 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4540 EXPECT_EQ(0, visitor
.continuation_count_
);
4541 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4542 EXPECT_EQ(0, visitor
.data_frame_count_
);
4545 TEST_P(SpdyFramerTest
, EndSegmentOnDataFrame
) {
4546 if (spdy_version_
<= SPDY3
) {
4549 const unsigned char kInput
[] = {
4550 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4551 0x00, 0x00, 0x00, 0x01, // Stream 1
4552 0xde, 0xad, 0xbe, 0xef,
4553 0xde, 0xad, 0xbe, 0xef,
4554 0xde, 0xad, 0xbe, 0xef,
4557 TestSpdyVisitor
visitor(spdy_version_
);
4558 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4560 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4561 EXPECT_EQ(0, visitor
.error_count_
);
4562 EXPECT_EQ(12, visitor
.data_bytes_
);
4563 EXPECT_EQ(0, visitor
.fin_frame_count_
);
4564 EXPECT_EQ(0, visitor
.fin_flag_count_
);
4567 TEST_P(SpdyFramerTest
, EndSegmentOnHeadersFrame
) {
4568 if (spdy_version_
<= SPDY3
) {
4571 const unsigned char kInput
[] = {
4572 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4573 0x00, 0x00, 0x00, 0x01, // Stream 1
4574 0x00, 0x06, 0x63, 0x6f,
4575 0x6f, 0x6b, 0x69, 0x65,
4576 0x07, 0x66, 0x6f, 0x6f,
4577 0x3d, 0x62, 0x61, 0x72,
4580 TestSpdyVisitor
visitor(spdy_version_
);
4581 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4583 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4584 EXPECT_EQ(0, visitor
.error_count_
);
4585 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4586 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4588 EXPECT_THAT(visitor
.headers_
,
4589 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4592 TEST_P(SpdyFramerTest
, ReadGarbage
) {
4593 SpdyFramer
framer(spdy_version_
);
4594 unsigned char garbage_frame
[256];
4595 memset(garbage_frame
, ~0, sizeof(garbage_frame
));
4596 TestSpdyVisitor
visitor(spdy_version_
);
4597 visitor
.use_compression_
= false;
4598 visitor
.SimulateInFramer(garbage_frame
, sizeof(garbage_frame
));
4599 EXPECT_EQ(1, visitor
.error_count_
);
4602 TEST_P(SpdyFramerTest
, ReadUnknownExtensionFrame
) {
4603 if (spdy_version_
<= SPDY3
) {
4606 SpdyFramer
framer(spdy_version_
);
4608 // The unrecognized frame type should still have a valid length.
4609 const unsigned char unknown_frame
[] = {
4610 0x00, 0x00, 0x08, 0xff, 0xff,
4611 0xff, 0xff, 0xff, 0xff,
4612 0xff, 0xff, 0xff, 0xff,
4613 0xff, 0xff, 0xff, 0xff,
4615 TestSpdyVisitor
visitor(spdy_version_
);
4617 // Simulate the case where the stream id validation checks out.
4618 visitor
.on_unknown_frame_result_
= true;
4619 visitor
.use_compression_
= false;
4620 visitor
.SimulateInFramer(unknown_frame
, arraysize(unknown_frame
));
4621 EXPECT_EQ(0, visitor
.error_count_
);
4623 // Follow it up with a valid control frame to make sure we handle
4624 // subsequent frames correctly.
4625 SpdySettingsIR settings_ir
;
4626 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
4630 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
4631 visitor
.SimulateInFramer(
4632 reinterpret_cast<unsigned char*>(control_frame
->data()),
4633 control_frame
->size());
4634 EXPECT_EQ(0, visitor
.error_count_
);
4635 EXPECT_EQ(1u, static_cast<unsigned>(visitor
.setting_count_
));
4636 EXPECT_EQ(1u, static_cast<unsigned>(visitor
.settings_ack_sent_
));
4639 TEST_P(SpdyFramerTest
, ReadGarbageWithValidLength
) {
4643 SpdyFramer
framer(spdy_version_
);
4644 const unsigned char kFrameData
[] = {
4645 0x00, 0x00, 0x08, 0xff, 0xff,
4646 0xff, 0xff, 0xff, 0xff,
4647 0xff, 0xff, 0xff, 0xff,
4648 0xff, 0xff, 0xff, 0xff,
4650 TestSpdyVisitor
visitor(spdy_version_
);
4651 visitor
.use_compression_
= false;
4652 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
4653 EXPECT_EQ(1, visitor
.error_count_
);
4656 TEST_P(SpdyFramerTest
, ReadGarbageWithValidVersion
) {
4658 // Not valid for SPDY 4 since there is no version field.
4661 SpdyFramer
framer(spdy_version_
);
4662 const unsigned char kFrameData
[] = {
4663 0x80, spdy_version_ch_
, 0xff, 0xff,
4664 0xff, 0xff, 0xff, 0xff,
4666 TestSpdyVisitor
visitor(spdy_version_
);
4667 visitor
.use_compression_
= false;
4668 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
4669 EXPECT_EQ(1, visitor
.error_count_
);
4672 TEST_P(SpdyFramerTest
, ReadGarbageHPACKEncoding
) {
4673 if (spdy_version_
<= SPDY3
) {
4676 const unsigned char kInput
[] = {
4677 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4678 0x00, 0x00, 0x00, 0x01, // Stream 1
4679 0xef, 0xef, 0xff, 0xff,
4680 0xff, 0xff, 0xff, 0xff,
4681 0xff, 0xff, 0xff, 0xff,
4682 0xff, 0xff, 0xff, 0xff,
4686 TestSpdyVisitor
visitor(spdy_version_
);
4687 visitor
.SimulateInFramer(kInput
, arraysize(kInput
));
4688 EXPECT_EQ(1, visitor
.error_count_
);
4691 TEST_P(SpdyFramerTest
, SizesTest
) {
4692 SpdyFramer
framer(spdy_version_
);
4694 EXPECT_EQ(9u, framer
.GetDataFrameMinimumSize());
4695 EXPECT_EQ(9u, framer
.GetControlFrameHeaderSize());
4696 EXPECT_EQ(14u, framer
.GetSynStreamMinimumSize());
4697 EXPECT_EQ(9u, framer
.GetSynReplyMinimumSize());
4698 EXPECT_EQ(13u, framer
.GetRstStreamMinimumSize());
4699 EXPECT_EQ(9u, framer
.GetSettingsMinimumSize());
4700 EXPECT_EQ(17u, framer
.GetPingSize());
4701 EXPECT_EQ(17u, framer
.GetGoAwayMinimumSize());
4702 EXPECT_EQ(9u, framer
.GetHeadersMinimumSize());
4703 EXPECT_EQ(13u, framer
.GetWindowUpdateSize());
4704 EXPECT_EQ(9u, framer
.GetBlockedSize());
4705 EXPECT_EQ(13u, framer
.GetPushPromiseMinimumSize());
4706 EXPECT_EQ(11u, framer
.GetAltSvcMinimumSize());
4707 EXPECT_EQ(9u, framer
.GetFrameMinimumSize());
4708 EXPECT_EQ(16393u, framer
.GetFrameMaximumSize());
4709 EXPECT_EQ(16384u, framer
.GetDataFrameMaximumPayload());
4711 EXPECT_EQ(8u, framer
.GetDataFrameMinimumSize());
4712 EXPECT_EQ(8u, framer
.GetControlFrameHeaderSize());
4713 EXPECT_EQ(18u, framer
.GetSynStreamMinimumSize());
4714 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetSynReplyMinimumSize());
4715 EXPECT_EQ(16u, framer
.GetRstStreamMinimumSize());
4716 EXPECT_EQ(12u, framer
.GetSettingsMinimumSize());
4717 EXPECT_EQ(12u, framer
.GetPingSize());
4718 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer
.GetGoAwayMinimumSize());
4719 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetHeadersMinimumSize());
4720 EXPECT_EQ(16u, framer
.GetWindowUpdateSize());
4721 EXPECT_EQ(8u, framer
.GetFrameMinimumSize());
4722 EXPECT_EQ(16777223u, framer
.GetFrameMaximumSize());
4723 EXPECT_EQ(16777215u, framer
.GetDataFrameMaximumPayload());
4727 TEST_P(SpdyFramerTest
, StateToStringTest
) {
4728 EXPECT_STREQ("ERROR",
4729 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR
));
4730 EXPECT_STREQ("AUTO_RESET",
4731 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET
));
4732 EXPECT_STREQ("RESET",
4733 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET
));
4734 EXPECT_STREQ("READING_COMMON_HEADER",
4735 SpdyFramer::StateToString(
4736 SpdyFramer::SPDY_READING_COMMON_HEADER
));
4737 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4738 SpdyFramer::StateToString(
4739 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD
));
4740 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4741 SpdyFramer::StateToString(
4742 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD
));
4743 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4744 SpdyFramer::StateToString(
4745 SpdyFramer::SPDY_FORWARD_STREAM_FRAME
));
4746 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4747 SpdyFramer::StateToString(
4748 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
));
4749 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4750 SpdyFramer::StateToString(
4751 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK
));
4752 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4753 SpdyFramer::StateToString(
4754 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD
));
4755 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4756 SpdyFramer::StateToString(
4757 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD
));
4758 EXPECT_STREQ("UNKNOWN_STATE",
4759 SpdyFramer::StateToString(
4760 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD
+ 1));
4763 TEST_P(SpdyFramerTest
, ErrorCodeToStringTest
) {
4764 EXPECT_STREQ("NO_ERROR",
4765 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR
));
4766 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4767 SpdyFramer::ErrorCodeToString(
4768 SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4769 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4770 SpdyFramer::ErrorCodeToString(
4771 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4772 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4773 SpdyFramer::ErrorCodeToString(
4774 SpdyFramer::SPDY_ZLIB_INIT_FAILURE
));
4775 EXPECT_STREQ("UNSUPPORTED_VERSION",
4776 SpdyFramer::ErrorCodeToString(
4777 SpdyFramer::SPDY_UNSUPPORTED_VERSION
));
4778 EXPECT_STREQ("DECOMPRESS_FAILURE",
4779 SpdyFramer::ErrorCodeToString(
4780 SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4781 EXPECT_STREQ("COMPRESS_FAILURE",
4782 SpdyFramer::ErrorCodeToString(
4783 SpdyFramer::SPDY_COMPRESS_FAILURE
));
4784 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4785 SpdyFramer::ErrorCodeToString(
4786 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4787 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4788 SpdyFramer::ErrorCodeToString(
4789 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
));
4790 EXPECT_STREQ("UNKNOWN_ERROR",
4791 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR
));
4794 TEST_P(SpdyFramerTest
, StatusCodeToStringTest
) {
4795 EXPECT_STREQ("INVALID",
4796 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID
));
4797 EXPECT_STREQ("PROTOCOL_ERROR",
4798 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR
));
4799 EXPECT_STREQ("INVALID_STREAM",
4800 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM
));
4801 EXPECT_STREQ("REFUSED_STREAM",
4802 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM
));
4803 EXPECT_STREQ("UNSUPPORTED_VERSION",
4804 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION
));
4805 EXPECT_STREQ("CANCEL",
4806 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL
));
4807 EXPECT_STREQ("INTERNAL_ERROR",
4808 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR
));
4809 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4810 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR
));
4811 EXPECT_STREQ("UNKNOWN_STATUS",
4812 SpdyFramer::StatusCodeToString(-1));
4815 TEST_P(SpdyFramerTest
, FrameTypeToStringTest
) {
4816 EXPECT_STREQ("DATA",
4817 SpdyFramer::FrameTypeToString(DATA
));
4818 EXPECT_STREQ("SYN_STREAM",
4819 SpdyFramer::FrameTypeToString(SYN_STREAM
));
4820 EXPECT_STREQ("SYN_REPLY",
4821 SpdyFramer::FrameTypeToString(SYN_REPLY
));
4822 EXPECT_STREQ("RST_STREAM",
4823 SpdyFramer::FrameTypeToString(RST_STREAM
));
4824 EXPECT_STREQ("SETTINGS",
4825 SpdyFramer::FrameTypeToString(SETTINGS
));
4826 EXPECT_STREQ("PING",
4827 SpdyFramer::FrameTypeToString(PING
));
4828 EXPECT_STREQ("GOAWAY",
4829 SpdyFramer::FrameTypeToString(GOAWAY
));
4830 EXPECT_STREQ("HEADERS",
4831 SpdyFramer::FrameTypeToString(HEADERS
));
4832 EXPECT_STREQ("WINDOW_UPDATE",
4833 SpdyFramer::FrameTypeToString(WINDOW_UPDATE
));
4834 EXPECT_STREQ("PUSH_PROMISE",
4835 SpdyFramer::FrameTypeToString(PUSH_PROMISE
));
4836 EXPECT_STREQ("CREDENTIAL",
4837 SpdyFramer::FrameTypeToString(CREDENTIAL
));
4838 EXPECT_STREQ("CONTINUATION",
4839 SpdyFramer::FrameTypeToString(CONTINUATION
));
4842 TEST_P(SpdyFramerTest
, CatchProbableHttpResponse
) {
4844 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4848 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4849 SpdyFramer
framer(spdy_version_
);
4850 framer
.set_visitor(&visitor
);
4852 EXPECT_CALL(visitor
, OnError(_
));
4853 framer
.ProcessInput("HTTP/1.1", 8);
4854 EXPECT_TRUE(framer
.probable_http_response());
4855 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4856 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4857 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4860 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4861 SpdyFramer
framer(spdy_version_
);
4862 framer
.set_visitor(&visitor
);
4864 EXPECT_CALL(visitor
, OnError(_
));
4865 framer
.ProcessInput("HTTP/1.0", 8);
4866 EXPECT_TRUE(framer
.probable_http_response());
4867 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4868 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4869 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4873 TEST_P(SpdyFramerTest
, DataFrameFlagsV2V3
) {
4874 if (spdy_version_
> SPDY3
) {
4880 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4882 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4883 SpdyFramer
framer(spdy_version_
);
4884 framer
.set_visitor(&visitor
);
4886 SpdyDataIR
data_ir(1, "hello");
4887 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4888 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4890 if (flags
& ~DATA_FLAG_FIN
) {
4891 EXPECT_CALL(visitor
, OnError(_
));
4893 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
4894 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
4895 if (flags
& DATA_FLAG_FIN
) {
4896 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4900 framer
.ProcessInput(frame
->data(), frame
->size());
4901 if (flags
& ~DATA_FLAG_FIN
) {
4902 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4903 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
,
4904 framer
.error_code())
4905 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4907 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4908 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4909 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4911 } while (++flags
!= 0);
4914 TEST_P(SpdyFramerTest
, DataFrameFlagsV4
) {
4915 if (spdy_version_
<= SPDY3
) {
4919 uint8 valid_data_flags
= DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
|
4924 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4926 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4927 SpdyFramer
framer(spdy_version_
);
4928 framer
.set_visitor(&visitor
);
4930 SpdyDataIR
data_ir(1, "hello");
4931 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4932 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4934 if (flags
& ~valid_data_flags
) {
4935 EXPECT_CALL(visitor
, OnError(_
));
4937 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
4938 if (flags
& DATA_FLAG_PADDED
) {
4939 // The first byte of payload is parsed as padding length.
4940 EXPECT_CALL(visitor
, OnStreamPadding(_
, 1));
4941 // Expect Error since the frame ends prematurely.
4942 EXPECT_CALL(visitor
, OnError(_
));
4944 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
4945 if (flags
& DATA_FLAG_FIN
) {
4946 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4951 framer
.ProcessInput(frame
->data(), frame
->size());
4952 if ((flags
& ~valid_data_flags
) || (flags
& DATA_FLAG_PADDED
)) {
4953 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4954 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4955 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4957 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4958 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4959 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4961 } while (++flags
!= 0);
4964 TEST_P(SpdyFramerTest
, SynStreamFrameFlags
) {
4965 if (!IsSpdy2() && !IsSpdy3()) {
4966 // SYN_STREAM not supported in SPDY>3
4971 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4973 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4974 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
4975 SpdyFramer
framer(spdy_version_
);
4976 framer
.set_visitor(&visitor
);
4977 framer
.set_debug_visitor(&debug_visitor
);
4979 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(8, SYN_STREAM
, _
, _
));
4981 SpdySynStreamIR
syn_stream(8);
4982 syn_stream
.set_associated_to_stream_id(3);
4983 syn_stream
.set_priority(1);
4984 syn_stream
.SetHeader("foo", "bar");
4985 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
4986 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4988 if (flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
4989 EXPECT_CALL(visitor
, OnError(_
));
4991 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(8, SYN_STREAM
, _
));
4992 EXPECT_CALL(visitor
, OnSynStream(8, 3, 1, flags
& CONTROL_FLAG_FIN
,
4993 flags
& CONTROL_FLAG_UNIDIRECTIONAL
));
4994 EXPECT_CALL(visitor
, OnControlFrameHeaderData(8, _
, _
))
4995 .WillRepeatedly(testing::Return(true));
4996 if (flags
& DATA_FLAG_FIN
) {
4997 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4999 // Do not close the stream if we are expecting a CONTINUATION frame.
5000 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
5004 framer
.ProcessInput(frame
->data(), frame
->size());
5005 if (flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
5006 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5007 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5008 framer
.error_code())
5009 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5011 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5012 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5013 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5015 } while (++flags
!= 0);
5018 TEST_P(SpdyFramerTest
, SynReplyFrameFlags
) {
5019 if (!IsSpdy2() && !IsSpdy3()) {
5020 // SYN_REPLY not supported in SPDY>3
5025 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5027 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5028 SpdyFramer
framer(spdy_version_
);
5029 framer
.set_visitor(&visitor
);
5031 SpdySynReplyIR
syn_reply(37);
5032 syn_reply
.SetHeader("foo", "bar");
5033 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
5034 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5036 if (flags
& ~CONTROL_FLAG_FIN
) {
5037 EXPECT_CALL(visitor
, OnError(_
));
5039 EXPECT_CALL(visitor
, OnSynReply(37, flags
& CONTROL_FLAG_FIN
));
5040 EXPECT_CALL(visitor
, OnControlFrameHeaderData(37, _
, _
))
5041 .WillRepeatedly(testing::Return(true));
5042 if (flags
& DATA_FLAG_FIN
) {
5043 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
5047 framer
.ProcessInput(frame
->data(), frame
->size());
5048 if (flags
& ~CONTROL_FLAG_FIN
) {
5049 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5050 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5051 framer
.error_code())
5052 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5054 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5055 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5056 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5058 } while (++flags
!= 0);
5061 TEST_P(SpdyFramerTest
, RstStreamFrameFlags
) {
5064 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5066 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5067 SpdyFramer
framer(spdy_version_
);
5068 framer
.set_visitor(&visitor
);
5070 SpdyRstStreamIR
rst_stream(13, RST_STREAM_CANCEL
, "");
5071 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
5072 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5075 EXPECT_CALL(visitor
, OnError(_
));
5077 EXPECT_CALL(visitor
, OnRstStream(13, RST_STREAM_CANCEL
));
5080 framer
.ProcessInput(frame
->data(), frame
->size());
5082 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5083 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5084 framer
.error_code())
5085 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5087 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5088 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5089 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5091 } while (++flags
!= 0);
5094 TEST_P(SpdyFramerTest
, SettingsFrameFlagsOldFormat
) {
5095 if (spdy_version_
> SPDY3
) { return; }
5098 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5100 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5101 SpdyFramer
framer(spdy_version_
);
5102 framer
.set_visitor(&visitor
);
5104 SpdySettingsIR settings_ir
;
5105 settings_ir
.AddSetting(SETTINGS_UPLOAD_BANDWIDTH
,
5109 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
5110 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5112 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
5113 EXPECT_CALL(visitor
, OnError(_
));
5115 EXPECT_CALL(visitor
, OnSettings(
5116 flags
& SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
));
5117 EXPECT_CALL(visitor
, OnSetting(SETTINGS_UPLOAD_BANDWIDTH
,
5118 SETTINGS_FLAG_NONE
, 54321));
5119 EXPECT_CALL(visitor
, OnSettingsEnd());
5122 framer
.ProcessInput(frame
->data(), frame
->size());
5123 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
5124 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5125 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5126 framer
.error_code())
5127 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5129 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5130 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5131 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5133 } while (++flags
!= 0);
5136 TEST_P(SpdyFramerTest
, SettingsFrameFlags
) {
5137 if (spdy_version_
<= SPDY3
) { return; }
5140 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5142 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5143 SpdyFramer
framer(spdy_version_
);
5144 framer
.set_visitor(&visitor
);
5146 SpdySettingsIR settings_ir
;
5147 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 0, 16);
5148 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
5149 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5152 EXPECT_CALL(visitor
, OnError(_
));
5154 EXPECT_CALL(visitor
, OnSettings(flags
& SETTINGS_FLAG_ACK
));
5155 EXPECT_CALL(visitor
, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 16));
5156 EXPECT_CALL(visitor
, OnSettingsEnd());
5159 framer
.ProcessInput(frame
->data(), frame
->size());
5160 if (flags
& ~SETTINGS_FLAG_ACK
) {
5161 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5162 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5163 framer
.error_code())
5164 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5165 } else if (flags
& SETTINGS_FLAG_ACK
) {
5166 // The frame is invalid because ACK frames should have no payload.
5167 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5168 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5169 framer
.error_code())
5170 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5172 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5173 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5174 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5176 } while (++flags
!= 0);
5179 TEST_P(SpdyFramerTest
, GoawayFrameFlags
) {
5182 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5184 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5185 SpdyFramer
framer(spdy_version_
);
5186 framer
.set_visitor(&visitor
);
5188 SpdyGoAwayIR
goaway_ir(97, GOAWAY_OK
, "test");
5189 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
5190 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5193 EXPECT_CALL(visitor
, OnError(_
));
5195 EXPECT_CALL(visitor
, OnGoAway(97, GOAWAY_OK
));
5198 framer
.ProcessInput(frame
->data(), frame
->size());
5200 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5201 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5202 framer
.error_code())
5203 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5205 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5206 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5207 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5209 } while (++flags
!= 0);
5212 TEST_P(SpdyFramerTest
, HeadersFrameFlags
) {
5215 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5217 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5218 SpdyFramer
framer(spdy_version_
);
5219 framer
.set_visitor(&visitor
);
5221 SpdyHeadersIR
headers_ir(57);
5222 if (IsSpdy4() && (flags
& HEADERS_FLAG_PRIORITY
)) {
5223 headers_ir
.set_priority(3);
5224 headers_ir
.set_has_priority(true);
5226 headers_ir
.SetHeader("foo", "bar");
5227 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
5228 uint8 set_flags
= flags
;
5230 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5231 // and implement framing.
5232 set_flags
&= ~HEADERS_FLAG_PADDED
;
5234 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
5236 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
5237 EXPECT_CALL(visitor
, OnError(_
));
5238 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
5239 HEADERS_FLAG_END_HEADERS
|
5240 HEADERS_FLAG_END_SEGMENT
|
5241 HEADERS_FLAG_PADDED
|
5242 HEADERS_FLAG_PRIORITY
)) {
5243 EXPECT_CALL(visitor
, OnError(_
));
5245 if (spdy_version_
> SPDY3
&& flags
& HEADERS_FLAG_PRIORITY
) {
5246 EXPECT_CALL(visitor
, OnHeaders(57, // stream id
5247 true, // has priority?
5249 flags
& CONTROL_FLAG_FIN
, // fin?
5250 (flags
& HEADERS_FLAG_END_HEADERS
) ||
5251 !IsSpdy4())); // end headers?
5253 EXPECT_CALL(visitor
, OnHeaders(57, false, 0,
5254 flags
& CONTROL_FLAG_FIN
,
5255 (flags
& HEADERS_FLAG_END_HEADERS
) ||
5258 EXPECT_CALL(visitor
, OnControlFrameHeaderData(57, _
, _
))
5259 .WillRepeatedly(testing::Return(true));
5260 if (flags
& DATA_FLAG_FIN
&& (!IsSpdy4() ||
5261 flags
& HEADERS_FLAG_END_HEADERS
)) {
5262 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
5264 // Do not close the stream if we are expecting a CONTINUATION frame.
5265 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
5269 framer
.ProcessInput(frame
->data(), frame
->size());
5270 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
5271 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5272 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5273 framer
.error_code())
5274 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5275 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
5276 HEADERS_FLAG_END_HEADERS
|
5277 HEADERS_FLAG_END_SEGMENT
|
5278 HEADERS_FLAG_PADDED
|
5279 HEADERS_FLAG_PRIORITY
)) {
5280 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5281 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5282 framer
.error_code())
5283 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5284 } else if (IsSpdy4() && ~(flags
& HEADERS_FLAG_END_HEADERS
)) {
5285 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5286 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5287 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5289 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5290 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5291 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5293 } while (++flags
!= 0);
5296 TEST_P(SpdyFramerTest
, PingFrameFlags
) {
5299 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5301 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5302 SpdyFramer
framer(spdy_version_
);
5303 framer
.set_visitor(&visitor
);
5305 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePing(SpdyPingIR(42)));
5306 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5308 if (spdy_version_
> SPDY3
&&
5309 flags
== PING_FLAG_ACK
) {
5310 EXPECT_CALL(visitor
, OnPing(42, true));
5311 } else if (flags
== 0) {
5312 EXPECT_CALL(visitor
, OnPing(42, false));
5314 EXPECT_CALL(visitor
, OnError(_
));
5317 framer
.ProcessInput(frame
->data(), frame
->size());
5318 if ((spdy_version_
> SPDY3
&& flags
== PING_FLAG_ACK
) ||
5320 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5321 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5322 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5324 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5325 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5326 framer
.error_code())
5327 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5329 } while (++flags
!= 0);
5332 TEST_P(SpdyFramerTest
, WindowUpdateFrameFlags
) {
5335 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5337 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5338 SpdyFramer
framer(spdy_version_
);
5339 framer
.set_visitor(&visitor
);
5341 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
5342 SpdyWindowUpdateIR(4, 1024)));
5343 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5346 EXPECT_CALL(visitor
, OnError(_
));
5348 EXPECT_CALL(visitor
, OnWindowUpdate(4, 1024));
5351 framer
.ProcessInput(frame
->data(), frame
->size());
5353 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5354 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5355 framer
.error_code())
5356 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5358 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5359 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5360 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5362 } while (++flags
!= 0);
5365 TEST_P(SpdyFramerTest
, PushPromiseFrameFlags
) {
5366 if (spdy_version_
<= SPDY3
) {
5372 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5374 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5375 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
5376 SpdyFramer
framer(spdy_version_
);
5377 framer
.set_visitor(&visitor
);
5378 framer
.set_debug_visitor(&debug_visitor
);
5380 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, PUSH_PROMISE
, _
, _
));
5382 SpdyPushPromiseIR
push_promise(42, 57);
5383 push_promise
.SetHeader("foo", "bar");
5384 scoped_ptr
<SpdySerializedFrame
> frame(
5385 framer
.SerializePushPromise(push_promise
));
5386 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5387 // and implement framing.
5388 SetFrameFlags(frame
.get(), flags
& ~HEADERS_FLAG_PADDED
, spdy_version_
);
5390 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
| HEADERS_FLAG_PADDED
)) {
5391 EXPECT_CALL(visitor
, OnError(_
));
5393 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, PUSH_PROMISE
, _
));
5394 EXPECT_CALL(visitor
, OnPushPromise(42, 57,
5395 flags
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
));
5396 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
5397 .WillRepeatedly(testing::Return(true));
5400 framer
.ProcessInput(frame
->data(), frame
->size());
5401 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
| HEADERS_FLAG_PADDED
)) {
5402 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5403 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5404 framer
.error_code())
5405 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5407 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5408 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5409 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5411 } while (++flags
!= 0);
5414 TEST_P(SpdyFramerTest
, ContinuationFrameFlags
) {
5415 if (spdy_version_
<= SPDY3
) {
5421 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5423 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5424 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
5425 SpdyFramer
framer(spdy_version_
);
5426 framer
.set_visitor(&visitor
);
5427 framer
.set_debug_visitor(&debug_visitor
);
5429 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, HEADERS
, _
, _
));
5430 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, HEADERS
, _
));
5431 EXPECT_CALL(visitor
, OnHeaders(42, false, 0, 0, false));
5432 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
5433 .WillRepeatedly(testing::Return(true));
5435 SpdyHeadersIR
headers_ir(42);
5436 headers_ir
.SetHeader("foo", "bar");
5437 scoped_ptr
<SpdyFrame
> frame0(framer
.SerializeHeaders(headers_ir
));
5438 SetFrameFlags(frame0
.get(), 0, spdy_version_
);
5440 SpdyContinuationIR
continuation(42);
5441 continuation
.SetHeader("foo", "bar");
5442 scoped_ptr
<SpdySerializedFrame
> frame(
5443 framer
.SerializeContinuation(continuation
));
5444 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5446 if (flags
& ~(HEADERS_FLAG_END_HEADERS
)) {
5447 EXPECT_CALL(visitor
, OnError(_
));
5449 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, CONTINUATION
, _
));
5450 EXPECT_CALL(visitor
, OnContinuation(42,
5451 flags
& HEADERS_FLAG_END_HEADERS
));
5452 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
5453 .WillRepeatedly(testing::Return(true));
5456 framer
.ProcessInput(frame0
->data(), frame0
->size());
5457 framer
.ProcessInput(frame
->data(), frame
->size());
5458 if (flags
& ~(HEADERS_FLAG_END_HEADERS
)) {
5459 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5460 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5461 framer
.error_code())
5462 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5464 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5465 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5466 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5468 } while (++flags
!= 0);
5471 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5473 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5475 TEST_P(SpdyFramerTest
, EmptySynStream
) {
5476 if (!IsSpdy2() && !IsSpdy3()) {
5477 // SYN_STREAM not supported in SPDY>3.
5480 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5481 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
5482 SpdyFramer
framer(spdy_version_
);
5483 framer
.set_visitor(&visitor
);
5484 framer
.set_debug_visitor(&debug_visitor
);
5486 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(1, SYN_STREAM
, _
, _
));
5488 SpdySynStreamIR
syn_stream(1);
5489 syn_stream
.set_priority(1);
5490 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
5491 // Adjust size to remove the name/value block.
5494 framer
.GetSynStreamMinimumSize() - framer
.GetControlFrameHeaderSize(),
5497 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(1, SYN_STREAM
, _
));
5498 EXPECT_CALL(visitor
, OnSynStream(1, 0, 1, false, false));
5499 EXPECT_CALL(visitor
, OnControlFrameHeaderData(1, NULL
, 0));
5501 framer
.ProcessInput(frame
->data(), framer
.GetSynStreamMinimumSize());
5502 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5503 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5504 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5507 TEST_P(SpdyFramerTest
, SettingsFlagsAndId
) {
5508 const uint32 kId
= 0x020304;
5509 const uint32 kFlags
= 0x01;
5510 const uint32 kWireFormat
= htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5512 SettingsFlagsAndId id_and_flags
=
5513 SettingsFlagsAndId::FromWireFormat(spdy_version_
, kWireFormat
);
5514 EXPECT_EQ(kId
, id_and_flags
.id());
5515 EXPECT_EQ(kFlags
, id_and_flags
.flags());
5516 EXPECT_EQ(kWireFormat
, id_and_flags
.GetWireFormat(spdy_version_
));
5519 // Test handling of a RST_STREAM with out-of-bounds status codes.
5520 TEST_P(SpdyFramerTest
, RstStreamStatusBounds
) {
5521 const unsigned char kRstStreamStatusTooLow
= 0x00;
5522 const unsigned char kRstStreamStatusTooHigh
= 0xff;
5523 const unsigned char kV3RstStreamInvalid
[] = {
5524 0x80, spdy_version_ch_
, 0x00, 0x03,
5525 0x00, 0x00, 0x00, 0x08,
5526 0x00, 0x00, 0x00, 0x01,
5527 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5529 const unsigned char kV4RstStreamInvalid
[] = {
5530 0x00, 0x00, 0x04, 0x03,
5531 0x00, 0x00, 0x00, 0x00,
5532 0x01, 0x00, 0x00, 0x00,
5533 kRstStreamStatusTooLow
5536 const unsigned char kV3RstStreamNumStatusCodes
[] = {
5537 0x80, spdy_version_ch_
, 0x00, 0x03,
5538 0x00, 0x00, 0x00, 0x08,
5539 0x00, 0x00, 0x00, 0x01,
5540 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5542 const unsigned char kV4RstStreamNumStatusCodes
[] = {
5543 0x00, 0x00, 0x04, 0x03,
5544 0x00, 0x00, 0x00, 0x00,
5545 0x01, 0x00, 0x00, 0x00,
5546 kRstStreamStatusTooHigh
5549 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5550 SpdyFramer
framer(spdy_version_
);
5551 framer
.set_visitor(&visitor
);
5554 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INTERNAL_ERROR
));
5555 framer
.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid
),
5556 arraysize(kV4RstStreamInvalid
));
5558 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
5559 framer
.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid
),
5560 arraysize(kV3RstStreamInvalid
));
5562 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5563 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5564 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5570 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INTERNAL_ERROR
));
5571 framer
.ProcessInput(
5572 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes
),
5573 arraysize(kV4RstStreamNumStatusCodes
));
5575 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
5576 framer
.ProcessInput(
5577 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes
),
5578 arraysize(kV3RstStreamNumStatusCodes
));
5580 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5581 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5582 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5585 // Test handling of GOAWAY frames with out-of-bounds status code.
5586 TEST_P(SpdyFramerTest
, GoAwayStatusBounds
) {
5587 if (spdy_version_
<= SPDY2
) {
5590 SpdyFramer
framer(spdy_version_
);
5592 const unsigned char kV3FrameData
[] = {
5593 0x80, spdy_version_ch_
, 0x00, 0x07,
5594 0x00, 0x00, 0x00, 0x08,
5595 0x00, 0x00, 0x00, 0x01, // Stream Id
5596 0xff, 0xff, 0xff, 0xff, // Status
5598 const unsigned char kV4FrameData
[] = {
5599 0x00, 0x00, 0x0a, 0x07,
5600 0x00, 0x00, 0x00, 0x00,
5601 0x00, 0x00, 0x00, 0x00, // Stream id
5602 0x01, 0xff, 0xff, 0xff, // Status
5603 0xff, 0x47, 0x41, // Opaque Description
5605 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5606 framer
.set_visitor(&visitor
);
5609 EXPECT_CALL(visitor
, OnGoAway(1, GOAWAY_OK
));
5610 framer
.ProcessInput(reinterpret_cast<const char*>(kV3FrameData
),
5611 arraysize(kV3FrameData
));
5613 EXPECT_CALL(visitor
, OnGoAway(1, GOAWAY_INTERNAL_ERROR
));
5614 framer
.ProcessInput(reinterpret_cast<const char*>(kV4FrameData
),
5615 arraysize(kV4FrameData
));
5617 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5618 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5619 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5622 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5623 TEST_P(SpdyFramerTest
, GoAwayStreamIdBounds
) {
5624 const unsigned char kV2FrameData
[] = {
5625 0x80, spdy_version_ch_
, 0x00, 0x07,
5626 0x00, 0x00, 0x00, 0x04,
5627 0xff, 0xff, 0xff, 0xff,
5629 const unsigned char kV3FrameData
[] = {
5630 0x80, spdy_version_ch_
, 0x00, 0x07,
5631 0x00, 0x00, 0x00, 0x08,
5632 0xff, 0xff, 0xff, 0xff,
5633 0x00, 0x00, 0x00, 0x00,
5635 const unsigned char kV4FrameData
[] = {
5636 0x00, 0x00, 0x08, 0x07,
5637 0x00, 0x00, 0x00, 0x00,
5638 0x00, 0xff, 0xff, 0xff,
5639 0xff, 0x00, 0x00, 0x00,
5643 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5644 SpdyFramer
framer(spdy_version_
);
5645 framer
.set_visitor(&visitor
);
5647 EXPECT_CALL(visitor
, OnGoAway(0x7fffffff, GOAWAY_OK
));
5649 framer
.ProcessInput(reinterpret_cast<const char*>(kV2FrameData
),
5650 arraysize(kV2FrameData
));
5651 } else if (IsSpdy3()) {
5652 framer
.ProcessInput(reinterpret_cast<const char*>(kV3FrameData
),
5653 arraysize(kV3FrameData
));
5655 framer
.ProcessInput(reinterpret_cast<const char*>(kV4FrameData
),
5656 arraysize(kV4FrameData
));
5658 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5659 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5660 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5663 TEST_P(SpdyFramerTest
, OnBlocked
) {
5664 if (spdy_version_
<= SPDY3
) {
5668 const SpdyStreamId kStreamId
= 0;
5670 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5671 SpdyFramer
framer(spdy_version_
);
5672 framer
.set_visitor(&visitor
);
5674 EXPECT_CALL(visitor
, OnBlocked(kStreamId
));
5676 SpdyBlockedIR
blocked_ir(0);
5677 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
5678 framer
.ProcessInput(frame
->data(), framer
.GetBlockedSize());
5680 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5681 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5682 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5685 TEST_P(SpdyFramerTest
, OnAltSvc
) {
5686 if (spdy_version_
<= SPDY3
) {
5690 const SpdyStreamId kStreamId
= 1;
5692 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5693 SpdyFramer
framer(spdy_version_
);
5694 framer
.set_visitor(&visitor
);
5696 SpdyAltSvcWireFormat::AlternativeService altsvc
;
5697 altsvc
.protocol_id
= "p\"=i:d";
5698 altsvc
.host
= "h_\\o\"st";
5700 altsvc
.max_age
= 10;
5702 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
, StringPiece("o_r|g!n"), altsvc
));
5704 SpdyAltSvcIR
altsvc_ir(1);
5705 altsvc_ir
.set_max_age(10);
5706 altsvc_ir
.set_port(443);
5707 altsvc_ir
.set_protocol_id("p\"=i:d");
5708 altsvc_ir
.set_host("h_\\o\"st");
5709 altsvc_ir
.set_origin("o_r|g!n");
5710 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5711 framer
.ProcessInput(frame
->data(), frame
->size());
5713 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5714 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5715 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5718 TEST_P(SpdyFramerTest
, OnAltSvcNoOrigin
) {
5719 if (spdy_version_
<= SPDY3
) {
5723 const SpdyStreamId kStreamId
= 1;
5725 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5726 SpdyFramer
framer(spdy_version_
);
5727 framer
.set_visitor(&visitor
);
5729 SpdyAltSvcWireFormat::AlternativeService altsvc
;
5730 altsvc
.protocol_id
= "p\"=i:d";
5731 altsvc
.host
= "h_\\o\"st";
5733 altsvc
.max_age
= 10;
5735 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
, StringPiece(""), altsvc
));
5737 SpdyAltSvcIR
altsvc_ir(1);
5738 altsvc_ir
.set_max_age(10);
5739 altsvc_ir
.set_port(443);
5740 altsvc_ir
.set_protocol_id("p\"=i:d");
5741 altsvc_ir
.set_host("h_\\o\"st");
5742 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5743 framer
.ProcessInput(frame
->data(), frame
->size());
5745 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5746 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5747 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5750 TEST_P(SpdyFramerTest
, OnAltSvcEmptyProtocolId
) {
5751 if (spdy_version_
<= SPDY3
) {
5755 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5756 SpdyFramer
framer(spdy_version_
);
5757 framer
.set_visitor(&visitor
);
5759 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
5761 SpdyAltSvcIR
altsvc_ir(1);
5762 altsvc_ir
.set_max_age(10);
5763 altsvc_ir
.set_port(443);
5764 altsvc_ir
.set_host("h1");
5765 altsvc_ir
.set_origin("o1");
5766 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5767 framer
.ProcessInput(frame
->data(), frame
->size());
5769 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5770 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
5771 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5774 TEST_P(SpdyFramerTest
, OnAltSvcBadLengths
) {
5775 if (spdy_version_
<= SPDY3
) {
5779 const SpdyStreamId kStreamId
= 1;
5781 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5782 SpdyFramer
framer(spdy_version_
);
5783 framer
.set_visitor(&visitor
);
5785 SpdyAltSvcWireFormat::AlternativeService altsvc
;
5786 altsvc
.protocol_id
= "pid";
5789 altsvc
.max_age
= 10;
5791 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
, StringPiece(""), altsvc
));
5793 SpdyAltSvcIR
altsvc_ir(1);
5794 altsvc_ir
.set_max_age(10);
5795 altsvc_ir
.set_port(443);
5796 altsvc_ir
.set_protocol_id("pid");
5797 altsvc_ir
.set_host("h1");
5798 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5799 framer
.ProcessInput(frame
->data(), frame
->size());
5801 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5802 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5803 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5806 // Tests handling of ALTSVC frames delivered in small chunks.
5807 TEST_P(SpdyFramerTest
, ReadChunkedAltSvcFrame
) {
5808 if (spdy_version_
<= SPDY3
) {
5812 SpdyFramer
framer(spdy_version_
);
5813 SpdyAltSvcIR
altsvc_ir(1);
5814 altsvc_ir
.set_max_age(20);
5815 altsvc_ir
.set_port(443);
5816 altsvc_ir
.set_protocol_id("protocolid");
5817 altsvc_ir
.set_host("hostname");
5819 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeAltSvc(altsvc_ir
));
5820 TestSpdyVisitor
visitor(spdy_version_
);
5821 visitor
.use_compression_
= false;
5823 // Read data in small chunks.
5824 size_t framed_data
= 0;
5825 size_t unframed_data
= control_frame
->size();
5826 size_t kReadChunkSize
= 5; // Read five bytes at a time.
5827 while (unframed_data
> 0) {
5828 size_t to_read
= std::min(kReadChunkSize
, unframed_data
);
5829 visitor
.SimulateInFramer(
5830 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
5832 unframed_data
-= to_read
;
5833 framed_data
+= to_read
;
5835 EXPECT_EQ(0, visitor
.error_count_
);
5836 EXPECT_EQ(1, visitor
.altsvc_count_
);
5837 EXPECT_EQ(20u, visitor
.test_altsvc_ir_
.max_age());
5838 EXPECT_EQ(443u, visitor
.test_altsvc_ir_
.port());
5839 EXPECT_EQ("protocolid", visitor
.test_altsvc_ir_
.protocol_id());
5840 EXPECT_EQ("hostname", visitor
.test_altsvc_ir_
.host());
5843 // Tests handling of PRIORITY frames.
5844 TEST_P(SpdyFramerTest
, ReadPriority
) {
5845 if (spdy_version_
<= SPDY3
) {
5848 SpdyFramer
framer(spdy_version_
);
5849 SpdyPriorityIR
priority(3, 1, 255, false);
5850 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializePriority(priority
));
5851 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5852 framer
.set_visitor(&visitor
);
5853 EXPECT_CALL(visitor
, OnPriority(3, 1, 255, false));
5854 framer
.ProcessInput(frame
->data(), frame
->size());
5856 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5857 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5858 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5859 // TODO(mlavan): once we actually maintain a priority tree,
5860 // check that state is adjusted correctly.
5863 TEST_P(SpdyFramerTest
, PriorityWeightMapping
) {
5864 if (spdy_version_
<= SPDY3
) {
5867 SpdyFramer
framer(spdy_version_
);
5869 EXPECT_EQ(255u, framer
.MapPriorityToWeight(0));
5870 EXPECT_EQ(219u, framer
.MapPriorityToWeight(1));
5871 EXPECT_EQ(182u, framer
.MapPriorityToWeight(2));
5872 EXPECT_EQ(146u, framer
.MapPriorityToWeight(3));
5873 EXPECT_EQ(109u, framer
.MapPriorityToWeight(4));
5874 EXPECT_EQ(73u, framer
.MapPriorityToWeight(5));
5875 EXPECT_EQ(36u, framer
.MapPriorityToWeight(6));
5876 EXPECT_EQ(0u, framer
.MapPriorityToWeight(7));
5878 EXPECT_EQ(0u, framer
.MapWeightToPriority(255));
5879 EXPECT_EQ(0u, framer
.MapWeightToPriority(220));
5880 EXPECT_EQ(1u, framer
.MapWeightToPriority(219));
5881 EXPECT_EQ(1u, framer
.MapWeightToPriority(183));
5882 EXPECT_EQ(2u, framer
.MapWeightToPriority(182));
5883 EXPECT_EQ(2u, framer
.MapWeightToPriority(147));
5884 EXPECT_EQ(3u, framer
.MapWeightToPriority(146));
5885 EXPECT_EQ(3u, framer
.MapWeightToPriority(110));
5886 EXPECT_EQ(4u, framer
.MapWeightToPriority(109));
5887 EXPECT_EQ(4u, framer
.MapWeightToPriority(74));
5888 EXPECT_EQ(5u, framer
.MapWeightToPriority(73));
5889 EXPECT_EQ(5u, framer
.MapWeightToPriority(37));
5890 EXPECT_EQ(6u, framer
.MapWeightToPriority(36));
5891 EXPECT_EQ(6u, framer
.MapWeightToPriority(1));
5892 EXPECT_EQ(7u, framer
.MapWeightToPriority(0));
5895 // Tests handling of PRIORITY frame with incorrect size.
5896 TEST_P(SpdyFramerTest
, ReadIncorrectlySizedPriority
) {
5897 if (spdy_version_
<= SPDY3
) {
5901 // PRIORITY frame of size 4, which isn't correct.
5902 const unsigned char kFrameData
[] = {
5903 0x00, 0x00, 0x04, 0x02, 0x00,
5904 0x00, 0x00, 0x00, 0x03,
5905 0x00, 0x00, 0x00, 0x01,
5908 TestSpdyVisitor
visitor(spdy_version_
);
5909 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
5911 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, visitor
.framer_
.state());
5912 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5913 visitor
.framer_
.error_code())
5914 << SpdyFramer::ErrorCodeToString(visitor
.framer_
.error_code());