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_
;
430 void OnAltSvc(SpdyStreamId stream_id
,
433 StringPiece protocol_id
,
435 StringPiece origin
) override
{
436 test_altsvc_ir_
.set_stream_id(stream_id
);
437 test_altsvc_ir_
.set_max_age(max_age
);
438 test_altsvc_ir_
.set_port(port
);
439 test_altsvc_ir_
.set_protocol_id(protocol_id
.as_string());
440 test_altsvc_ir_
.set_host(host
.as_string());
441 if (origin
.length() > 0) {
442 test_altsvc_ir_
.set_origin(origin
.as_string());
447 void OnPriority(SpdyStreamId stream_id
,
448 SpdyStreamId parent_stream_id
,
450 bool exclusive
) override
{
454 bool OnUnknownFrame(SpdyStreamId stream_id
, int frame_type
) override
{
455 DLOG(INFO
) << "Unknown frame type " << frame_type
;
456 return on_unknown_frame_result_
;
459 void OnSendCompressedFrame(SpdyStreamId stream_id
,
462 size_t frame_len
) override
{
463 last_payload_len_
= payload_len
;
464 last_frame_len_
= frame_len
;
467 void OnReceiveCompressedFrame(SpdyStreamId stream_id
,
469 size_t frame_len
) override
{
470 last_frame_len_
= frame_len
;
473 // Convenience function which runs a framer simulation with particular input.
474 void SimulateInFramer(const unsigned char* input
, size_t size
) {
475 framer_
.set_enable_compression(use_compression_
);
476 framer_
.set_visitor(this);
477 size_t input_remaining
= size
;
478 const char* input_ptr
= reinterpret_cast<const char*>(input
);
479 while (input_remaining
> 0 &&
480 framer_
.error_code() == SpdyFramer::SPDY_NO_ERROR
) {
481 // To make the tests more interesting, we feed random (amd small) chunks
482 // into the framer. This simulates getting strange-sized reads from
484 const size_t kMaxReadSize
= 32;
486 (rand() % std::min(input_remaining
, kMaxReadSize
)) + 1;
487 size_t bytes_processed
= framer_
.ProcessInput(input_ptr
, bytes_read
);
488 input_remaining
-= bytes_processed
;
489 input_ptr
+= bytes_processed
;
493 void InitHeaderStreaming(SpdyFrameType header_control_type
,
494 SpdyStreamId stream_id
) {
495 if (!SpdyConstants::IsValidFrameType(framer_
.protocol_version(),
496 SpdyConstants::SerializeFrameType(framer_
.protocol_version(),
497 header_control_type
))) {
498 DLOG(FATAL
) << "Attempted to init header streaming with "
499 << "invalid control frame type: "
500 << header_control_type
;
502 memset(header_buffer_
.get(), 0, header_buffer_size_
);
503 header_buffer_length_
= 0;
504 header_stream_id_
= stream_id
;
505 header_control_type_
= header_control_type
;
506 header_buffer_valid_
= true;
507 DCHECK_NE(header_stream_id_
, SpdyFramer::kInvalidStream
);
510 // Override the default buffer size (16K). Call before using the framer!
511 void set_header_buffer_size(size_t header_buffer_size
) {
512 header_buffer_size_
= header_buffer_size
;
513 header_buffer_
.reset(new char[header_buffer_size
]);
516 // Largest control frame that the SPDY implementation sends, including the
517 // size of the header.
518 static size_t sent_control_frame_max_size() {
519 return SpdyFramer::kMaxControlFrameSize
;
522 static size_t header_data_chunk_max_size() {
523 return SpdyFramer::kHeaderDataChunkMaxSize
;
527 bool use_compression_
;
529 // Counters from the visitor callbacks.
531 int syn_frame_count_
;
532 int syn_reply_frame_count_
;
533 int headers_frame_count_
;
534 int push_promise_frame_count_
;
537 int settings_ack_sent_
;
538 int settings_ack_received_
;
539 int continuation_count_
;
542 SpdyAltSvcIR test_altsvc_ir_
;
543 bool on_unknown_frame_result_
;
544 SpdyStreamId last_window_update_stream_
;
545 uint32 last_window_update_delta_
;
546 SpdyStreamId last_push_promise_stream_
;
547 SpdyStreamId last_push_promise_promised_stream_
;
549 int fin_frame_count_
; // The count of RST_STREAM type frames received.
550 string fin_opaque_data_
;
551 int fin_flag_count_
; // The count of frames with the FIN flag set.
552 int zero_length_data_frame_count_
; // The count of zero-length data frames.
553 int control_frame_header_data_count_
; // The count of chunks received.
554 // The count of zero-length control frame header data chunks received.
555 int zero_length_control_frame_header_data_count_
;
556 int data_frame_count_
;
557 size_t last_payload_len_
;
558 size_t last_frame_len_
;
560 // Header block streaming state:
561 scoped_ptr
<char[]> header_buffer_
;
562 size_t header_buffer_length_
;
563 size_t header_buffer_size_
;
564 SpdyStreamId header_stream_id_
;
565 SpdyFrameType header_control_type_
;
566 bool header_buffer_valid_
;
567 SpdyHeaderBlock headers_
;
570 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
571 base::StringPiece
GetSerializedHeaders(const SpdyFrame
* frame
,
572 const SpdyFramer
& framer
) {
573 SpdyFrameReader
reader(frame
->data(), frame
->size());
574 if (framer
.protocol_version() > SPDY3
) {
575 reader
.Seek(3); // Seek past the frame length.
577 reader
.Seek(2); // Seek past the frame length.
579 SpdyFrameType frame_type
;
580 if (framer
.protocol_version() > SPDY3
) {
581 uint8 serialized_type
;
582 reader
.ReadUInt8(&serialized_type
);
583 frame_type
= SpdyConstants::ParseFrameType(framer
.protocol_version(),
585 DCHECK_EQ(HEADERS
, frame_type
);
587 reader
.ReadUInt8(&flags
);
588 if (flags
& HEADERS_FLAG_PRIORITY
) {
589 frame_type
= SYN_STREAM
;
592 uint16 serialized_type
;
593 reader
.ReadUInt16(&serialized_type
);
594 frame_type
= SpdyConstants::ParseFrameType(framer
.protocol_version(),
596 DCHECK(frame_type
== HEADERS
||
597 frame_type
== SYN_STREAM
) << frame_type
;
600 if (frame_type
== SYN_STREAM
) {
601 return StringPiece(frame
->data() + framer
.GetSynStreamMinimumSize(),
602 frame
->size() - framer
.GetSynStreamMinimumSize());
604 return StringPiece(frame
->data() + framer
.GetHeadersMinimumSize(),
605 frame
->size() - framer
.GetHeadersMinimumSize());
611 using test::SetFrameLength
;
612 using test::SetFrameFlags
;
613 using test::CompareCharArraysWithHexError
;
614 using test::SpdyFramerTestUtil
;
615 using test::TestSpdyVisitor
;
616 using test::GetSerializedHeaders
;
618 class SpdyFramerTest
: public ::testing::TestWithParam
<SpdyMajorVersion
> {
620 void SetUp() override
{
621 spdy_version_
= GetParam();
622 spdy_version_ch_
= static_cast<unsigned char>(
623 SpdyConstants::SerializeMajorVersion(spdy_version_
));
626 void CompareFrame(const string
& description
,
627 const SpdyFrame
& actual_frame
,
628 const unsigned char* expected
,
629 const int expected_len
) {
630 const unsigned char* actual
=
631 reinterpret_cast<const unsigned char*>(actual_frame
.data());
632 CompareCharArraysWithHexError(
633 description
, actual
, actual_frame
.size(), expected
, expected_len
);
636 void CompareFrames(const string
& description
,
637 const SpdyFrame
& expected_frame
,
638 const SpdyFrame
& actual_frame
) {
639 CompareCharArraysWithHexError(
641 reinterpret_cast<const unsigned char*>(expected_frame
.data()),
642 expected_frame
.size(),
643 reinterpret_cast<const unsigned char*>(actual_frame
.data()),
644 actual_frame
.size());
647 // Returns true if the two header blocks have equivalent content.
648 bool CompareHeaderBlocks(const SpdyHeaderBlock
* expected
,
649 const SpdyHeaderBlock
* actual
) {
650 if (expected
->size() != actual
->size()) {
651 LOG(ERROR
) << "Expected " << expected
->size() << " headers; actually got "
652 << actual
->size() << ".";
655 for (SpdyHeaderBlock::const_iterator it
= expected
->begin();
656 it
!= expected
->end();
658 SpdyHeaderBlock::const_iterator it2
= actual
->find(it
->first
);
659 if (it2
== actual
->end()) {
660 LOG(ERROR
) << "Expected header name '" << it
->first
<< "'.";
663 if (it
->second
.compare(it2
->second
) != 0) {
664 LOG(ERROR
) << "Expected header named '" << it
->first
665 << "' to have a value of '" << it
->second
666 << "'. The actual value received was '" << it2
->second
674 bool IsSpdy2() { return spdy_version_
== SPDY2
; }
675 bool IsSpdy3() { return spdy_version_
== SPDY3
; }
676 bool IsSpdy4() { return spdy_version_
== SPDY4
; }
678 // Version of SPDY protocol to be used.
679 SpdyMajorVersion spdy_version_
;
680 unsigned char spdy_version_ch_
;
683 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
684 INSTANTIATE_TEST_CASE_P(SpdyFramerTests
,
686 ::testing::Values(SPDY2
, SPDY3
, SPDY4
));
688 // Test that we ignore cookie where both name and value are empty.
689 TEST_P(SpdyFramerTest
, HeaderBlockWithEmptyCookie
) {
690 if (spdy_version_
> SPDY3
) {
691 // Not implemented for hpack.
695 SpdyFramer
framer(spdy_version_
);
696 framer
.set_enable_compression(true);
697 SpdyHeadersIR
headers(1);
698 headers
.set_priority(1);
699 headers
.SetHeader("cookie",
700 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
701 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
702 EXPECT_TRUE(frame
.get() != NULL
);
704 TestSpdyVisitor
visitor(spdy_version_
);
705 visitor
.use_compression_
= true;
706 visitor
.SimulateInFramer(
707 reinterpret_cast<unsigned char*>(frame
->data()),
710 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
711 EXPECT_FALSE(CompareHeaderBlocks(&headers
.name_value_block(),
713 EXPECT_EQ(1u, visitor
.headers_
.size());
714 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor
.headers_
["cookie"]);
717 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
718 TEST_P(SpdyFramerTest
, HeaderBlockInBuffer
) {
719 SpdyFramer
framer(spdy_version_
);
720 framer
.set_enable_compression(false);
722 // Encode the header block into a Headers frame.
723 SpdyHeadersIR
headers(1);
724 headers
.set_priority(1);
725 headers
.SetHeader("alpha", "beta");
726 headers
.SetHeader("gamma", "charlie");
727 headers
.SetHeader("cookie", "key1=value1; key2=value2");
728 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
729 EXPECT_TRUE(frame
.get() != NULL
);
731 TestSpdyVisitor
visitor(spdy_version_
);
732 visitor
.use_compression_
= false;
733 visitor
.SimulateInFramer(
734 reinterpret_cast<unsigned char*>(frame
->data()),
737 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
738 EXPECT_TRUE(CompareHeaderBlocks(&headers
.name_value_block(),
742 // Test that if there's not a full frame, we fail to parse it.
743 TEST_P(SpdyFramerTest
, UndersizedHeaderBlockInBuffer
) {
744 SpdyFramer
framer(spdy_version_
);
745 framer
.set_enable_compression(false);
747 // Encode the header block into a Headers frame.
748 SpdyHeadersIR
headers(1);
749 headers
.set_priority(1);
750 headers
.SetHeader("alpha", "beta");
751 headers
.SetHeader("gamma", "charlie");
752 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers
));
753 EXPECT_TRUE(frame
.get() != NULL
);
755 TestSpdyVisitor
visitor(spdy_version_
);
756 visitor
.use_compression_
= false;
757 visitor
.SimulateInFramer(
758 reinterpret_cast<unsigned char*>(frame
->data()),
761 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
762 EXPECT_EQ(0u, visitor
.headers_
.size());
765 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
766 // (but don't crash).
767 TEST_P(SpdyFramerTest
, SynReplyWithStreamIdZero
) {
768 if (spdy_version_
> SPDY3
) {
771 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
772 SpdyFramer
framer(spdy_version_
);
773 framer
.set_visitor(&visitor
);
775 SpdySynReplyIR
syn_reply(0);
776 syn_reply
.SetHeader("alpha", "beta");
777 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeSynReply(syn_reply
));
778 ASSERT_TRUE(frame
.get() != NULL
);
780 // We shouldn't have to read the whole frame before we signal an error.
781 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
782 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
783 EXPECT_TRUE(framer
.HasError());
784 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
785 << SpdyFramer::ErrorCodeToString(framer
.error_code());
788 // Test that if we receive a HEADERS with stream ID zero, we signal an error
789 // (but don't crash).
790 TEST_P(SpdyFramerTest
, HeadersWithStreamIdZero
) {
791 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
792 SpdyFramer
framer(spdy_version_
);
793 framer
.set_visitor(&visitor
);
795 SpdyHeadersIR
headers_ir(0);
796 headers_ir
.SetHeader("alpha", "beta");
797 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeHeaders(headers_ir
));
798 ASSERT_TRUE(frame
.get() != NULL
);
800 // We shouldn't have to read the whole frame before we signal an error.
801 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
802 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
803 EXPECT_TRUE(framer
.HasError());
804 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
805 << SpdyFramer::ErrorCodeToString(framer
.error_code());
808 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
809 // error (but don't crash).
810 TEST_P(SpdyFramerTest
, PushPromiseWithStreamIdZero
) {
811 if (spdy_version_
<= SPDY3
) {
815 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
816 SpdyFramer
framer(spdy_version_
);
817 framer
.set_visitor(&visitor
);
819 SpdyPushPromiseIR
push_promise(0, 4);
820 push_promise
.SetHeader("alpha", "beta");
821 scoped_ptr
<SpdySerializedFrame
> frame(
822 framer
.SerializePushPromise(push_promise
));
823 ASSERT_TRUE(frame
.get() != NULL
);
825 // We shouldn't have to read the whole frame before we signal an error.
826 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
827 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
828 EXPECT_TRUE(framer
.HasError());
829 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
830 << SpdyFramer::ErrorCodeToString(framer
.error_code());
833 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
834 // signal an error (but don't crash).
835 TEST_P(SpdyFramerTest
, PushPromiseWithPromisedStreamIdZero
) {
836 if (spdy_version_
<= SPDY3
) {
840 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
841 SpdyFramer
framer(spdy_version_
);
842 framer
.set_visitor(&visitor
);
844 SpdyPushPromiseIR
push_promise(3, 0);
845 push_promise
.SetHeader("alpha", "beta");
846 scoped_ptr
<SpdySerializedFrame
> frame(
847 framer
.SerializePushPromise(push_promise
));
848 ASSERT_TRUE(frame
.get() != NULL
);
850 // We shouldn't have to read the whole frame before we signal an error.
851 EXPECT_CALL(visitor
, OnError(testing::Eq(&framer
)));
852 EXPECT_GT(frame
->size(), framer
.ProcessInput(frame
->data(), frame
->size()));
853 EXPECT_TRUE(framer
.HasError());
854 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
, framer
.error_code())
855 << SpdyFramer::ErrorCodeToString(framer
.error_code());
858 TEST_P(SpdyFramerTest
, DuplicateHeader
) {
859 if (spdy_version_
> SPDY3
) {
860 // TODO(jgraettinger): Punting on this because we haven't determined
861 // whether duplicate HPACK headers other than Cookie are an error.
862 // If they are, this will need to be updated to use HpackOutputStream.
865 SpdyFramer
framer(spdy_version_
);
866 // Frame builder with plentiful buffer size.
867 SpdyFrameBuilder
frame(1024, spdy_version_
);
868 if (spdy_version_
<= SPDY3
) {
869 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
870 frame
.WriteUInt32(3); // stream_id
871 frame
.WriteUInt32(0); // associated stream id
872 frame
.WriteUInt16(0); // Priority.
874 frame
.BeginNewFrame(framer
, HEADERS
, HEADERS_FLAG_PRIORITY
, 3);
875 frame
.WriteUInt32(framer
.GetHighestPriority());
879 frame
.WriteUInt16(2); // Number of headers.
880 frame
.WriteStringPiece16("name");
881 frame
.WriteStringPiece16("value1");
882 frame
.WriteStringPiece16("name");
883 frame
.WriteStringPiece16("value2");
885 frame
.WriteUInt32(2); // Number of headers.
886 frame
.WriteStringPiece32("name");
887 frame
.WriteStringPiece32("value1");
888 frame
.WriteStringPiece32("name");
889 frame
.WriteStringPiece32("value2");
892 frame
.RewriteLength(framer
);
894 SpdyHeaderBlock new_headers
;
895 framer
.set_enable_compression(false);
896 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
897 base::StringPiece serialized_headers
=
898 GetSerializedHeaders(control_frame
.get(), framer
);
899 // This should fail because duplicate headers are verboten by the spec.
900 EXPECT_FALSE(framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
901 serialized_headers
.size(),
905 TEST_P(SpdyFramerTest
, MultiValueHeader
) {
906 SpdyFramer
framer(spdy_version_
);
907 // Frame builder with plentiful buffer size.
908 SpdyFrameBuilder
frame(1024, spdy_version_
);
909 if (spdy_version_
<= SPDY3
) {
910 frame
.WriteControlFrameHeader(framer
, SYN_STREAM
, CONTROL_FLAG_NONE
);
911 frame
.WriteUInt32(3); // stream_id
912 frame
.WriteUInt32(0); // associated stream id
913 frame
.WriteUInt16(0); // Priority.
915 frame
.BeginNewFrame(framer
,
917 HEADERS_FLAG_PRIORITY
| HEADERS_FLAG_END_HEADERS
,
919 frame
.WriteUInt32(0); // Priority exclusivity and dependent stream.
920 frame
.WriteUInt8(255); // Priority weight.
923 string
value("value1\0value2", 13);
925 frame
.WriteUInt16(1); // Number of headers.
926 frame
.WriteStringPiece16("name");
927 frame
.WriteStringPiece16(value
);
928 } else if (spdy_version_
> SPDY3
) {
929 // TODO(jgraettinger): If this pattern appears again, move to test class.
930 std::map
<string
, string
> header_set
;
931 header_set
["name"] = value
;
933 HpackEncoder
encoder(ObtainHpackHuffmanTable());
934 encoder
.EncodeHeaderSetWithoutCompression(header_set
, &buffer
);
935 frame
.WriteBytes(&buffer
[0], buffer
.size());
937 frame
.WriteUInt32(1); // Number of headers.
938 frame
.WriteStringPiece32("name");
939 frame
.WriteStringPiece32(value
);
942 frame
.RewriteLength(framer
);
944 framer
.set_enable_compression(false);
945 scoped_ptr
<SpdyFrame
> control_frame(frame
.take());
947 TestSpdyVisitor
visitor(spdy_version_
);
948 visitor
.use_compression_
= false;
949 visitor
.SimulateInFramer(
950 reinterpret_cast<unsigned char*>(control_frame
->data()),
951 control_frame
->size());
953 EXPECT_THAT(visitor
.headers_
,
954 testing::ElementsAre(testing::Pair("name", value
)));
957 TEST_P(SpdyFramerTest
, BasicCompression
) {
958 if (spdy_version_
> SPDY3
) {
959 // Deflate compression doesn't apply to HPACK.
962 scoped_ptr
<TestSpdyVisitor
> visitor(new TestSpdyVisitor(spdy_version_
));
963 SpdyFramer
framer(spdy_version_
);
964 framer
.set_debug_visitor(visitor
.get());
965 SpdySynStreamIR
syn_stream(1);
966 syn_stream
.set_priority(1);
967 syn_stream
.SetHeader("server", "SpdyServer 1.0");
968 syn_stream
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
969 syn_stream
.SetHeader("status", "200");
970 syn_stream
.SetHeader("version", "HTTP/1.1");
971 syn_stream
.SetHeader("content-type", "text/html");
972 syn_stream
.SetHeader("content-length", "12");
973 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeSynStream(syn_stream
));
974 size_t uncompressed_size1
= visitor
->last_payload_len_
;
975 size_t compressed_size1
=
976 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
978 EXPECT_EQ(139u, uncompressed_size1
);
979 #if defined(USE_SYSTEM_ZLIB)
980 EXPECT_EQ(155u, compressed_size1
);
981 #else // !defined(USE_SYSTEM_ZLIB)
982 EXPECT_EQ(135u, compressed_size1
);
983 #endif // !defined(USE_SYSTEM_ZLIB)
985 EXPECT_EQ(165u, uncompressed_size1
);
986 #if defined(USE_SYSTEM_ZLIB)
987 EXPECT_EQ(181u, compressed_size1
);
988 #else // !defined(USE_SYSTEM_ZLIB)
989 EXPECT_EQ(117u, compressed_size1
);
990 #endif // !defined(USE_SYSTEM_ZLIB)
992 scoped_ptr
<SpdyFrame
> frame2(framer
.SerializeSynStream(syn_stream
));
993 size_t uncompressed_size2
= visitor
->last_payload_len_
;
994 size_t compressed_size2
=
995 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
997 // Expect the second frame to be more compact than the first.
998 EXPECT_LE(frame2
->size(), frame1
->size());
1000 // Decompress the first frame
1001 scoped_ptr
<SpdyFrame
> frame3(
1002 SpdyFramerTestUtil::DecompressFrame(&framer
, *frame1
));
1004 // Decompress the second frame
1005 visitor
.reset(new TestSpdyVisitor(spdy_version_
));
1006 framer
.set_debug_visitor(visitor
.get());
1007 scoped_ptr
<SpdyFrame
> frame4(
1008 SpdyFramerTestUtil::DecompressFrame(&framer
, *frame2
));
1009 size_t uncompressed_size4
=
1010 frame4
->size() - framer
.GetSynStreamMinimumSize();
1011 size_t compressed_size4
=
1012 visitor
->last_frame_len_
- framer
.GetSynStreamMinimumSize();
1014 EXPECT_EQ(139u, uncompressed_size4
);
1015 #if defined(USE_SYSTEM_ZLIB)
1016 EXPECT_EQ(149u, compressed_size4
);
1017 #else // !defined(USE_SYSTEM_ZLIB)
1018 EXPECT_EQ(101u, compressed_size4
);
1019 #endif // !defined(USE_SYSTEM_ZLIB)
1021 EXPECT_EQ(165u, uncompressed_size4
);
1022 #if defined(USE_SYSTEM_ZLIB)
1023 EXPECT_EQ(175u, compressed_size4
);
1024 #else // !defined(USE_SYSTEM_ZLIB)
1025 EXPECT_EQ(102u, compressed_size4
);
1026 #endif // !defined(USE_SYSTEM_ZLIB)
1029 EXPECT_EQ(uncompressed_size1
, uncompressed_size2
);
1030 EXPECT_EQ(uncompressed_size1
, uncompressed_size4
);
1031 EXPECT_EQ(compressed_size2
, compressed_size4
);
1033 // Expect frames 3 & 4 to be the same.
1034 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *frame4
);
1036 // Expect frames 3 to be the same as a uncompressed frame created
1038 framer
.set_enable_compression(false);
1039 scoped_ptr
<SpdyFrame
> uncompressed_frame(
1040 framer
.SerializeSynStream(syn_stream
));
1041 CompareFrames("Uncompressed SYN_STREAM", *frame3
, *uncompressed_frame
);
1044 TEST_P(SpdyFramerTest
, CompressEmptyHeaders
) {
1045 // See crbug.com/172383
1046 SpdyHeadersIR
headers(1);
1047 headers
.SetHeader("server", "SpdyServer 1.0");
1048 headers
.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1049 headers
.SetHeader("status", "200");
1050 headers
.SetHeader("version", "HTTP/1.1");
1051 headers
.SetHeader("content-type", "text/html");
1052 headers
.SetHeader("content-length", "12");
1053 headers
.SetHeader("x-empty-header", "");
1055 SpdyFramer
framer(spdy_version_
);
1056 framer
.set_enable_compression(true);
1057 scoped_ptr
<SpdyFrame
> frame1(framer
.SerializeHeaders(headers
));
1060 TEST_P(SpdyFramerTest
, Basic
) {
1061 const unsigned char kV2Input
[] = {
1062 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1063 0x00, 0x00, 0x00, 0x14,
1064 0x00, 0x00, 0x00, 0x01,
1065 0x00, 0x00, 0x00, 0x00,
1066 0x00, 0x00, 0x00, 0x01,
1067 0x00, 0x02, 'h', 'h',
1068 0x00, 0x02, 'v', 'v',
1070 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
1071 0x00, 0x00, 0x00, 0x18,
1072 0x00, 0x00, 0x00, 0x01,
1073 0x00, 0x00, 0x00, 0x02,
1074 0x00, 0x02, 'h', '2',
1075 0x00, 0x02, 'v', '2',
1076 0x00, 0x02, 'h', '3',
1077 0x00, 0x02, 'v', '3',
1079 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1080 0x00, 0x00, 0x00, 0x0c,
1081 0xde, 0xad, 0xbe, 0xef,
1082 0xde, 0xad, 0xbe, 0xef,
1083 0xde, 0xad, 0xbe, 0xef,
1085 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1086 0x00, 0x00, 0x00, 0x0c,
1087 0x00, 0x00, 0x00, 0x03,
1088 0x00, 0x00, 0x00, 0x00,
1089 0x00, 0x00, 0x00, 0x00,
1091 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1092 0x00, 0x00, 0x00, 0x08,
1093 0xde, 0xad, 0xbe, 0xef,
1094 0xde, 0xad, 0xbe, 0xef,
1096 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1097 0x00, 0x00, 0x00, 0x04,
1098 0xde, 0xad, 0xbe, 0xef,
1100 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1101 0x00, 0x00, 0x00, 0x08,
1102 0x00, 0x00, 0x00, 0x01,
1103 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1105 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1106 0x00, 0x00, 0x00, 0x00,
1108 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1109 0x00, 0x00, 0x00, 0x08,
1110 0x00, 0x00, 0x00, 0x03,
1111 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1114 const unsigned char kV3Input
[] = {
1115 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1116 0x00, 0x00, 0x00, 0x1a,
1117 0x00, 0x00, 0x00, 0x01,
1118 0x00, 0x00, 0x00, 0x00,
1119 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x01, 0x00, 0x00,
1121 0x00, 0x02, 'h', 'h',
1122 0x00, 0x00, 0x00, 0x02,
1125 0x80, spdy_version_ch_
, 0x00, 0x08, // HEADERS on Stream #1
1126 0x00, 0x00, 0x00, 0x20,
1127 0x00, 0x00, 0x00, 0x01,
1128 0x00, 0x00, 0x00, 0x02,
1129 0x00, 0x00, 0x00, 0x02,
1131 0x00, 0x00, 0x00, 0x02,
1132 'v', '2', 0x00, 0x00,
1133 0x00, 0x02, 'h', '3',
1134 0x00, 0x00, 0x00, 0x02,
1137 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1138 0x00, 0x00, 0x00, 0x0c,
1139 0xde, 0xad, 0xbe, 0xef,
1140 0xde, 0xad, 0xbe, 0xef,
1141 0xde, 0xad, 0xbe, 0xef,
1143 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #3
1144 0x00, 0x00, 0x00, 0x0e,
1145 0x00, 0x00, 0x00, 0x03,
1146 0x00, 0x00, 0x00, 0x00,
1147 0x00, 0x00, 0x00, 0x00,
1150 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1151 0x00, 0x00, 0x00, 0x08,
1152 0xde, 0xad, 0xbe, 0xef,
1153 0xde, 0xad, 0xbe, 0xef,
1155 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1156 0x00, 0x00, 0x00, 0x04,
1157 0xde, 0xad, 0xbe, 0xef,
1159 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #1
1160 0x00, 0x00, 0x00, 0x08,
1161 0x00, 0x00, 0x00, 0x01,
1162 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1164 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1165 0x00, 0x00, 0x00, 0x00,
1167 0x80, spdy_version_ch_
, 0x00, 0x03, // RST_STREAM on Stream #3
1168 0x00, 0x00, 0x00, 0x08,
1169 0x00, 0x00, 0x00, 0x03,
1170 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1173 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1174 // HEADERS frames with PRIORITY and END_HEADERS set.
1175 const unsigned char kV4Input
[] = {
1176 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1177 0x24, 0x00, 0x00, 0x00,
1178 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1179 0x00, 0x82, // :method: GET
1181 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1182 0x04, 0x00, 0x00, 0x00, // Stream 1
1183 0x01, 0x8c, // :status: 200
1185 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1186 0x00, 0x00, 0x00, 0x00,
1187 0x01, 0xde, 0xad, 0xbe,
1188 0xef, 0xde, 0xad, 0xbe,
1189 0xef, 0xde, 0xad, 0xbe,
1192 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1193 0x24, 0x00, 0x00, 0x00,
1194 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1195 0x00, 0x82, // :method: GET
1197 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1198 0x00, 0x00, 0x00, 0x00,
1199 0x03, 0xde, 0xad, 0xbe,
1200 0xef, 0xde, 0xad, 0xbe,
1203 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1204 0x00, 0x00, 0x00, 0x00,
1205 0x01, 0xde, 0xad, 0xbe,
1208 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1209 0x00, 0x00, 0x00, 0x00,
1210 0x01, 0x00, 0x00, 0x00,
1211 0x08, // RST_STREAM_CANCEL
1213 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1214 0x00, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1218 0x00, 0x00, 0x00, 0x00,
1219 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1220 0x08, 0x52, 0x45, 0x53, // opaque data
1221 0x45, 0x54, 0x53, 0x54,
1222 0x52, 0x45, 0x41, 0x4d,
1225 TestSpdyVisitor
visitor(spdy_version_
);
1227 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1228 } else if (IsSpdy3()) {
1229 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1231 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1234 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1235 EXPECT_EQ(24, visitor
.data_bytes_
);
1236 EXPECT_EQ(0, visitor
.error_count_
);
1237 EXPECT_EQ(2, visitor
.fin_frame_count_
);
1240 EXPECT_EQ(3, visitor
.headers_frame_count_
);
1241 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1242 base::StringPiece reset_stream
= "RESETSTREAM";
1243 EXPECT_EQ(reset_stream
, visitor
.fin_opaque_data_
);
1245 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1246 EXPECT_EQ(2, visitor
.syn_frame_count_
);
1247 EXPECT_TRUE(visitor
.fin_opaque_data_
.empty());
1250 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1251 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
1252 EXPECT_EQ(4, visitor
.data_frame_count_
);
1253 visitor
.fin_opaque_data_
.clear();
1256 // Test that the FIN flag on a data frame signifies EOF.
1257 TEST_P(SpdyFramerTest
, FinOnDataFrame
) {
1258 const unsigned char kV2Input
[] = {
1259 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1260 0x00, 0x00, 0x00, 0x14,
1261 0x00, 0x00, 0x00, 0x01,
1262 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x01,
1264 0x00, 0x02, 'h', 'h',
1265 0x00, 0x02, 'v', 'v',
1267 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1268 0x00, 0x00, 0x00, 0x10,
1269 0x00, 0x00, 0x00, 0x01,
1270 0x00, 0x00, 0x00, 0x01,
1271 0x00, 0x02, 'a', 'a',
1272 0x00, 0x02, 'b', 'b',
1274 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1275 0x00, 0x00, 0x00, 0x0c,
1276 0xde, 0xad, 0xbe, 0xef,
1277 0xde, 0xad, 0xbe, 0xef,
1278 0xde, 0xad, 0xbe, 0xef,
1280 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1281 0x01, 0x00, 0x00, 0x04,
1282 0xde, 0xad, 0xbe, 0xef,
1284 const unsigned char kV3Input
[] = {
1285 0x80, spdy_version_ch_
, 0x00, 0x01, // SYN Stream #1
1286 0x00, 0x00, 0x00, 0x1a,
1287 0x00, 0x00, 0x00, 0x01,
1288 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x01, 0x00, 0x00,
1291 0x00, 0x02, 'h', 'h',
1292 0x00, 0x00, 0x00, 0x02,
1295 0x80, spdy_version_ch_
, 0x00, 0x02, // SYN REPLY Stream #1
1296 0x00, 0x00, 0x00, 0x14,
1297 0x00, 0x00, 0x00, 0x01,
1298 0x00, 0x00, 0x00, 0x01,
1299 0x00, 0x00, 0x00, 0x02,
1300 'a', 'a', 0x00, 0x00,
1301 0x00, 0x02, 'b', 'b',
1303 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1304 0x00, 0x00, 0x00, 0x0c,
1305 0xde, 0xad, 0xbe, 0xef,
1306 0xde, 0xad, 0xbe, 0xef,
1307 0xde, 0xad, 0xbe, 0xef,
1309 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1310 0x01, 0x00, 0x00, 0x04,
1311 0xde, 0xad, 0xbe, 0xef,
1314 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1315 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1316 const unsigned char kV4Input
[] = {
1317 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1318 0x24, 0x00, 0x00, 0x00, // Stream 1
1319 0x01, 0x00, 0x00, 0x00, // Priority 0
1320 0x00, 0x82, // :method: GET
1322 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1323 0x04, 0x00, 0x00, 0x00, // Stream 1
1324 0x01, 0x8c, // :status: 200
1326 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1327 0x00, 0x00, 0x00, 0x00,
1328 0x01, 0xde, 0xad, 0xbe,
1329 0xef, 0xde, 0xad, 0xbe,
1330 0xef, 0xde, 0xad, 0xbe,
1333 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1334 0x01, 0x00, 0x00, 0x00,
1335 0x01, 0xde, 0xad, 0xbe,
1339 TestSpdyVisitor
visitor(spdy_version_
);
1341 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1342 } else if (IsSpdy3()) {
1343 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1345 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1348 EXPECT_EQ(0, visitor
.error_count_
);
1350 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1351 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1352 EXPECT_EQ(2, visitor
.headers_frame_count_
);
1354 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1355 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1356 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1358 EXPECT_EQ(16, visitor
.data_bytes_
);
1359 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1360 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1361 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1362 EXPECT_EQ(2, visitor
.data_frame_count_
);
1365 // Test that the FIN flag on a SYN reply frame signifies EOF.
1366 TEST_P(SpdyFramerTest
, FinOnSynReplyFrame
) {
1367 const unsigned char kV2Input
[] = {
1368 0x80, spdy_version_ch_
, 0x00, // SYN Stream #1
1369 0x01, 0x00, 0x00, 0x00,
1370 0x14, 0x00, 0x00, 0x00,
1371 0x01, 0x00, 0x00, 0x00,
1372 0x00, 0x00, 0x00, 0x00,
1373 0x01, 0x00, 0x02, 'h',
1374 'h', 0x00, 0x02, 'v',
1377 0x80, spdy_version_ch_
, 0x00, // SYN REPLY Stream #1
1378 0x02, 0x01, 0x00, 0x00,
1379 0x10, 0x00, 0x00, 0x00,
1380 0x01, 0x00, 0x00, 0x00,
1381 0x01, 0x00, 0x02, 'a',
1382 'a', 0x00, 0x02, 'b',
1385 const unsigned char kV3Input
[] = {
1386 0x80, spdy_version_ch_
, 0x00, // SYN Stream #1
1387 0x01, 0x00, 0x00, 0x00,
1388 0x1a, 0x00, 0x00, 0x00,
1389 0x01, 0x00, 0x00, 0x00,
1390 0x00, 0x00, 0x00, 0x00,
1391 0x00, 0x00, 0x01, 0x00,
1392 0x00, 0x00, 0x02, 'h',
1393 'h', 0x00, 0x00, 0x00,
1396 0x80, spdy_version_ch_
, 0x00, // SYN REPLY Stream #1
1397 0x02, 0x01, 0x00, 0x00,
1398 0x14, 0x00, 0x00, 0x00,
1399 0x01, 0x00, 0x00, 0x00,
1400 0x01, 0x00, 0x00, 0x00,
1401 0x02, 'a', 'a', 0x00,
1402 0x00, 0x00, 0x02, 'b',
1406 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1407 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1408 const unsigned char kV4Input
[] = {
1409 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1410 0x24, 0x00, 0x00, 0x00,
1411 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1412 0x00, 0x82, // :method: GET
1414 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1415 0x05, 0x00, 0x00, 0x00,
1416 0x01, 0x8c, // Stream 1, :status: 200
1419 TestSpdyVisitor
visitor(spdy_version_
);
1421 visitor
.SimulateInFramer(kV2Input
, sizeof(kV2Input
));
1422 } else if (IsSpdy3()) {
1423 visitor
.SimulateInFramer(kV3Input
, sizeof(kV3Input
));
1425 visitor
.SimulateInFramer(kV4Input
, sizeof(kV4Input
));
1428 EXPECT_EQ(0, visitor
.error_count_
);
1430 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1431 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1432 EXPECT_EQ(2, visitor
.headers_frame_count_
);
1434 EXPECT_EQ(1, visitor
.syn_frame_count_
);
1435 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
1436 EXPECT_EQ(0, visitor
.headers_frame_count_
);
1438 EXPECT_EQ(0, visitor
.data_bytes_
);
1439 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1440 EXPECT_EQ(1, visitor
.fin_flag_count_
);
1441 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1442 EXPECT_EQ(0, visitor
.data_frame_count_
);
1445 TEST_P(SpdyFramerTest
, HeaderCompression
) {
1446 if (spdy_version_
> SPDY3
) {
1447 // Deflate compression doesn't apply to HPACK.
1450 SpdyFramer
send_framer(spdy_version_
);
1451 SpdyFramer
recv_framer(spdy_version_
);
1453 send_framer
.set_enable_compression(true);
1454 recv_framer
.set_enable_compression(true);
1456 const char kHeader1
[] = "header1";
1457 const char kHeader2
[] = "header2";
1458 const char kHeader3
[] = "header3";
1459 const char kValue1
[] = "value1";
1460 const char kValue2
[] = "value2";
1461 const char kValue3
[] = "value3";
1464 SpdyHeaderBlock block
;
1465 block
[kHeader1
] = kValue1
;
1466 block
[kHeader2
] = kValue2
;
1467 SpdySynStreamIR
syn_ir_1(1);
1468 syn_ir_1
.set_name_value_block(block
);
1469 scoped_ptr
<SpdyFrame
> syn_frame_1(send_framer
.SerializeFrame(syn_ir_1
));
1470 EXPECT_TRUE(syn_frame_1
.get() != NULL
);
1473 block
[kHeader3
] = kValue3
;
1474 SpdySynStreamIR
syn_stream(3);
1475 syn_stream
.set_name_value_block(block
);
1476 scoped_ptr
<SpdyFrame
> syn_frame_2(send_framer
.SerializeSynStream(syn_stream
));
1477 EXPECT_TRUE(syn_frame_2
.get() != NULL
);
1479 // Now start decompressing
1480 scoped_ptr
<SpdyFrame
> decompressed
;
1481 scoped_ptr
<SpdyFrame
> uncompressed
;
1482 base::StringPiece serialized_headers
;
1483 SpdyHeaderBlock decompressed_headers
;
1485 // Decompress SYN_STREAM #1
1487 SpdyFramerTestUtil::DecompressFrame(&recv_framer
, *syn_frame_1
));
1488 EXPECT_TRUE(decompressed
.get() != NULL
);
1489 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1490 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1491 serialized_headers
.size(),
1492 &decompressed_headers
));
1493 EXPECT_EQ(2u, decompressed_headers
.size());
1494 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1495 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1497 // Decompress SYN_STREAM #2
1499 SpdyFramerTestUtil::DecompressFrame(&recv_framer
, *syn_frame_2
));
1500 EXPECT_TRUE(decompressed
.get() != NULL
);
1501 serialized_headers
= GetSerializedHeaders(decompressed
.get(), send_framer
);
1502 decompressed_headers
.clear();
1503 EXPECT_TRUE(recv_framer
.ParseHeaderBlockInBuffer(serialized_headers
.data(),
1504 serialized_headers
.size(),
1505 &decompressed_headers
));
1506 EXPECT_EQ(3u, decompressed_headers
.size());
1507 EXPECT_EQ(kValue1
, decompressed_headers
[kHeader1
]);
1508 EXPECT_EQ(kValue2
, decompressed_headers
[kHeader2
]);
1509 EXPECT_EQ(kValue3
, decompressed_headers
[kHeader3
]);
1512 // Verify we can decompress the stream even if handed over to the
1513 // framer 1 byte at a time.
1514 TEST_P(SpdyFramerTest
, UnclosedStreamDataCompressorsOneByteAtATime
) {
1515 SpdyFramer
send_framer(spdy_version_
);
1517 send_framer
.set_enable_compression(true);
1519 const char kHeader1
[] = "header1";
1520 const char kHeader2
[] = "header2";
1521 const char kValue1
[] = "value1";
1522 const char kValue2
[] = "value2";
1524 SpdyHeadersIR
headers(1);
1525 headers
.SetHeader(kHeader1
, kValue1
);
1526 headers
.SetHeader(kHeader2
, kValue2
);
1527 scoped_ptr
<SpdyFrame
> headers_frame(send_framer
.SerializeHeaders(headers
));
1528 EXPECT_TRUE(headers_frame
.get() != NULL
);
1530 const char bytes
[] = "this is a test test test test test!";
1531 SpdyDataIR
data_ir(1, StringPiece(bytes
, arraysize(bytes
)));
1532 data_ir
.set_fin(true);
1533 scoped_ptr
<SpdyFrame
> send_frame(send_framer
.SerializeData(data_ir
));
1534 EXPECT_TRUE(send_frame
.get() != NULL
);
1536 // Run the inputs through the framer.
1537 TestSpdyVisitor
visitor(spdy_version_
);
1538 visitor
.use_compression_
= true;
1539 const unsigned char* data
;
1540 data
= reinterpret_cast<const unsigned char*>(headers_frame
->data());
1541 for (size_t idx
= 0; idx
< headers_frame
->size(); ++idx
) {
1542 visitor
.SimulateInFramer(data
+ idx
, 1);
1543 ASSERT_EQ(0, visitor
.error_count_
);
1545 data
= reinterpret_cast<const unsigned char*>(send_frame
->data());
1546 for (size_t idx
= 0; idx
< send_frame
->size(); ++idx
) {
1547 visitor
.SimulateInFramer(data
+ idx
, 1);
1548 ASSERT_EQ(0, visitor
.error_count_
);
1551 EXPECT_EQ(0, visitor
.error_count_
);
1552 EXPECT_EQ(0, visitor
.syn_frame_count_
);
1553 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
1554 EXPECT_EQ(1, visitor
.headers_frame_count_
);
1555 EXPECT_EQ(arraysize(bytes
), static_cast<unsigned>(visitor
.data_bytes_
));
1556 EXPECT_EQ(0, visitor
.fin_frame_count_
);
1557 EXPECT_EQ(0, visitor
.fin_flag_count_
);
1558 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
1559 EXPECT_EQ(1, visitor
.data_frame_count_
);
1562 TEST_P(SpdyFramerTest
, WindowUpdateFrame
) {
1563 SpdyFramer
framer(spdy_version_
);
1564 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
1565 SpdyWindowUpdateIR(1, 0x12345678)));
1567 const char kDescription
[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1568 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1569 0x80, spdy_version_ch_
, 0x00, 0x09,
1570 0x00, 0x00, 0x00, 0x08,
1571 0x00, 0x00, 0x00, 0x01,
1572 0x12, 0x34, 0x56, 0x78
1574 const unsigned char kV4FrameData
[] = {
1575 0x00, 0x00, 0x04, 0x08,
1576 0x00, 0x00, 0x00, 0x00,
1577 0x01, 0x12, 0x34, 0x56,
1582 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1584 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1588 TEST_P(SpdyFramerTest
, CreateDataFrame
) {
1589 SpdyFramer
framer(spdy_version_
);
1592 const char kDescription
[] = "'hello' data frame, no FIN";
1593 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1594 0x00, 0x00, 0x00, 0x01,
1595 0x00, 0x00, 0x00, 0x05,
1599 const unsigned char kV4FrameData
[] = {
1600 0x00, 0x00, 0x05, 0x00,
1601 0x00, 0x00, 0x00, 0x00,
1602 0x01, 'h', 'e', 'l',
1605 const char bytes
[] = "hello";
1607 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1608 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1611 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1614 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1617 SpdyDataIR
data_header_ir(1);
1618 data_header_ir
.SetDataShallow(base::StringPiece(bytes
, strlen(bytes
)));
1619 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(
1621 CompareCharArraysWithHexError(
1623 reinterpret_cast<const unsigned char*>(frame
->data()),
1624 framer
.GetDataFrameMinimumSize(),
1625 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1626 framer
.GetDataFrameMinimumSize());
1630 const char kDescription
[] = "'hello' data frame with more padding, no FIN";
1631 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1632 0x00, 0x00, 0x00, 0x01,
1633 0x00, 0x00, 0x00, 0x05,
1638 const unsigned char kV4FrameData
[] = {
1639 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1640 0x08, 0x00, 0x00, 0x00,
1641 0x01, 0xf7, // Pad length field.
1642 'h', 'e', 'l', 'l', // Data
1644 // Padding of 247 0x00(s).
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
1667 const char bytes
[] = "hello";
1669 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1670 // 247 zeros and the pad length field make the overall padding to be 248
1672 data_ir
.set_padding_len(248);
1673 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1676 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1679 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1682 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1683 CompareCharArraysWithHexError(
1685 reinterpret_cast<const unsigned char*>(frame
->data()),
1686 framer
.GetDataFrameMinimumSize(),
1687 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1688 framer
.GetDataFrameMinimumSize());
1692 const char kDescription
[] = "'hello' data frame with few padding, no FIN";
1693 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1694 0x00, 0x00, 0x00, 0x01,
1695 0x00, 0x00, 0x00, 0x05,
1700 const unsigned char kV4FrameData
[] = {
1701 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1702 0x08, 0x00, 0x00, 0x00,
1703 0x01, 0x07, // Pad length field.
1704 'h', 'e', 'l', 'l', // Data
1706 0x00, 0x00, 0x00, 0x00, // Padding
1709 const char bytes
[] = "hello";
1711 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1712 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1713 data_ir
.set_padding_len(8);
1714 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1717 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1720 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1725 const char kDescription
[] =
1726 "'hello' data frame with 1 byte padding, no FIN";
1727 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1728 0x00, 0x00, 0x00, 0x01,
1729 0x00, 0x00, 0x00, 0x05,
1734 const unsigned char kV4FrameData
[] = {
1735 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1736 0x08, 0x00, 0x00, 0x00,
1737 0x01, 0x00, // Pad length field.
1738 'h', 'e', 'l', 'l', // Data
1741 const char bytes
[] = "hello";
1743 SpdyDataIR
data_ir(1, StringPiece(bytes
, strlen(bytes
)));
1744 // The pad length field itself is used for the 1-byte padding and no padding
1745 // payload is needed.
1746 data_ir
.set_padding_len(1);
1747 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1750 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1753 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1756 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1757 CompareCharArraysWithHexError(
1759 reinterpret_cast<const unsigned char*>(frame
->data()),
1760 framer
.GetDataFrameMinimumSize(),
1761 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1762 framer
.GetDataFrameMinimumSize());
1766 const char kDescription
[] = "Data frame with negative data byte, no FIN";
1767 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1768 0x00, 0x00, 0x00, 0x01,
1769 0x00, 0x00, 0x00, 0x01,
1772 const unsigned char kV4FrameData
[] = {
1773 0x00, 0x00, 0x01, 0x00, 0x00,
1774 0x00, 0x00, 0x00, 0x01,
1777 SpdyDataIR
data_ir(1, StringPiece("\xff", 1));
1778 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1781 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1784 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1789 const char kDescription
[] = "'hello' data frame, with FIN";
1790 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1791 0x00, 0x00, 0x00, 0x01,
1792 0x01, 0x00, 0x00, 0x05,
1796 const unsigned char kV4FrameData
[] = {
1797 0x00, 0x00, 0x05, 0x00,
1798 0x01, 0x00, 0x00, 0x00,
1799 0x01, 'h', 'e', 'l',
1802 SpdyDataIR
data_ir(1, StringPiece("hello", 5));
1803 data_ir
.set_fin(true);
1804 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1807 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1810 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1815 const char kDescription
[] = "Empty data frame";
1816 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1817 0x00, 0x00, 0x00, 0x01,
1818 0x00, 0x00, 0x00, 0x00,
1820 const unsigned char kV4FrameData
[] = {
1821 0x00, 0x00, 0x00, 0x00,
1822 0x00, 0x00, 0x00, 0x00,
1825 SpdyDataIR
data_ir(1, StringPiece());
1826 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1829 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1832 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1835 frame
.reset(framer
.SerializeDataFrameHeaderWithPaddingLengthField(data_ir
));
1836 CompareCharArraysWithHexError(
1838 reinterpret_cast<const unsigned char*>(frame
->data()),
1839 framer
.GetDataFrameMinimumSize(),
1840 IsSpdy4() ? kV4FrameData
: kV3FrameData
,
1841 framer
.GetDataFrameMinimumSize());
1845 const char kDescription
[] = "Data frame with max stream ID";
1846 const unsigned char kV3FrameData
[] = { // Also applies for V2.
1847 0x7f, 0xff, 0xff, 0xff,
1848 0x01, 0x00, 0x00, 0x05,
1852 const unsigned char kV4FrameData
[] = {
1853 0x00, 0x00, 0x05, 0x00,
1854 0x01, 0x7f, 0xff, 0xff,
1855 0xff, 'h', 'e', 'l',
1858 SpdyDataIR
data_ir(0x7fffffff, "hello");
1859 data_ir
.set_fin(true);
1860 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1863 kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
1866 kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1871 // This test does not apply to SPDY 4 because the max frame size is smaller
1873 const char kDescription
[] = "Large data frame";
1874 const int kDataSize
= 4 * 1024 * 1024; // 4 MB
1875 const string
kData(kDataSize
, 'A');
1876 const unsigned char kFrameHeader
[] = {
1877 0x00, 0x00, 0x00, 0x01,
1878 0x01, 0x40, 0x00, 0x00,
1881 const int kFrameSize
= arraysize(kFrameHeader
) + kDataSize
;
1882 scoped_ptr
<unsigned char[]> expected_frame_data(
1883 new unsigned char[kFrameSize
]);
1884 memcpy(expected_frame_data
.get(), kFrameHeader
, arraysize(kFrameHeader
));
1885 memset(expected_frame_data
.get() + arraysize(kFrameHeader
), 'A', kDataSize
);
1887 SpdyDataIR
data_ir(1, StringPiece(kData
.data(), kData
.size()));
1888 data_ir
.set_fin(true);
1889 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
1890 CompareFrame(kDescription
, *frame
, expected_frame_data
.get(), kFrameSize
);
1894 TEST_P(SpdyFramerTest
, CreateSynStreamUncompressed
) {
1895 if (!IsSpdy2() && !IsSpdy3()) {
1896 // SYN_STREAM unsupported in SPDY>3
1899 SpdyFramer
framer(spdy_version_
);
1900 framer
.set_enable_compression(false);
1903 const char kDescription
[] = "SYN_STREAM frame, lowest pri, no FIN";
1905 const unsigned char kPri
= IsSpdy2() ? 0xC0 : 0xE0;
1906 const unsigned char kV2FrameData
[] = {
1907 0x80, spdy_version_ch_
, 0x00, 0x01,
1908 0x00, 0x00, 0x00, 0x20,
1909 0x00, 0x00, 0x00, 0x01,
1910 0x00, 0x00, 0x00, 0x00,
1911 kPri
, 0x00, 0x00, 0x02,
1912 0x00, 0x03, 'b', 'a',
1913 'r', 0x00, 0x03, 'f',
1914 'o', 'o', 0x00, 0x03,
1915 'f', 'o', 'o', 0x00,
1918 const unsigned char kV3FrameData
[] = {
1919 0x80, spdy_version_ch_
, 0x00, 0x01,
1920 0x00, 0x00, 0x00, 0x2a,
1921 0x00, 0x00, 0x00, 0x01,
1922 0x00, 0x00, 0x00, 0x00,
1923 kPri
, 0x00, 0x00, 0x00,
1924 0x00, 0x02, 0x00, 0x00,
1925 0x00, 0x03, 'b', 'a',
1926 'r', 0x00, 0x00, 0x00,
1927 0x03, 'f', 'o', 'o',
1928 0x00, 0x00, 0x00, 0x03,
1929 'f', 'o', 'o', 0x00,
1930 0x00, 0x00, 0x03, 'b',
1933 SpdySynStreamIR
syn_stream(1);
1934 syn_stream
.set_priority(framer
.GetLowestPriority());
1935 syn_stream
.SetHeader("bar", "foo");
1936 syn_stream
.SetHeader("foo", "bar");
1937 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1939 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1940 } else if (IsSpdy3()) {
1941 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1943 LOG(FATAL
) << "Unsupported version in test.";
1948 const char kDescription
[] =
1949 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1952 const unsigned char kV2FrameData
[] = {
1953 0x80, spdy_version_ch_
, 0x00, 0x01,
1954 0x01, 0x00, 0x00, 0x1D,
1955 0x7f, 0xff, 0xff, 0xff,
1956 0x7f, 0xff, 0xff, 0xff,
1957 0x00, 0x00, 0x00, 0x02,
1958 0x00, 0x00, 0x00, 0x03,
1959 'f', 'o', 'o', 0x00,
1960 0x03, 'f', 'o', 'o',
1961 0x00, 0x03, 'b', 'a',
1964 const unsigned char kV3FrameData
[] = {
1965 0x80, spdy_version_ch_
, 0x00, 0x01,
1966 0x01, 0x00, 0x00, 0x27,
1967 0x7f, 0xff, 0xff, 0xff,
1968 0x7f, 0xff, 0xff, 0xff,
1969 0x00, 0x00, 0x00, 0x00,
1970 0x00, 0x02, 0x00, 0x00,
1971 0x00, 0x00, 0x00, 0x00,
1972 0x00, 0x03, 'f', 'o',
1973 'o', 0x00, 0x00, 0x00,
1974 0x03, 'f', 'o', 'o',
1975 0x00, 0x00, 0x00, 0x03,
1978 SpdySynStreamIR
syn_stream(0x7fffffff);
1979 syn_stream
.set_associated_to_stream_id(0x7fffffff);
1980 syn_stream
.set_priority(framer
.GetHighestPriority());
1981 syn_stream
.set_fin(true);
1982 syn_stream
.SetHeader("", "foo");
1983 syn_stream
.SetHeader("foo", "bar");
1984 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
1986 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
1987 } else if (IsSpdy3()) {
1988 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
1990 LOG(FATAL
) << "Unsupported version in test.";
1995 const char kDescription
[] =
1996 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1999 const unsigned char kPri
= IsSpdy2() ? 0x40 : 0x20;
2000 const unsigned char kV2FrameData
[] = {
2001 0x80, spdy_version_ch_
, 0x00, 0x01,
2002 0x01, 0x00, 0x00, 0x1D,
2003 0x7f, 0xff, 0xff, 0xff,
2004 0x7f, 0xff, 0xff, 0xff,
2005 kPri
, 0x00, 0x00, 0x02,
2006 0x00, 0x03, 'b', 'a',
2007 'r', 0x00, 0x03, 'f',
2008 'o', 'o', 0x00, 0x03,
2009 'f', 'o', 'o', 0x00,
2012 const unsigned char kV3FrameData
[] = {
2013 0x80, spdy_version_ch_
, 0x00, 0x01,
2014 0x01, 0x00, 0x00, 0x27,
2015 0x7f, 0xff, 0xff, 0xff,
2016 0x7f, 0xff, 0xff, 0xff,
2017 kPri
, 0x00, 0x00, 0x00,
2018 0x00, 0x02, 0x00, 0x00,
2019 0x00, 0x03, 'b', 'a',
2020 'r', 0x00, 0x00, 0x00,
2021 0x03, 'f', 'o', 'o',
2022 0x00, 0x00, 0x00, 0x03,
2023 'f', 'o', 'o', 0x00,
2026 SpdySynStreamIR
syn_stream(0x7fffffff);
2027 syn_stream
.set_associated_to_stream_id(0x7fffffff);
2028 syn_stream
.set_priority(1);
2029 syn_stream
.set_fin(true);
2030 syn_stream
.SetHeader("bar", "foo");
2031 syn_stream
.SetHeader("foo", "");
2032 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
2034 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2035 } else if (IsSpdy3()) {
2036 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2038 LOG(FATAL
) << "Unsupported version in test.";
2043 // TODO(phajdan.jr): Clean up after we no longer need
2044 // to workaround http://crbug.com/139744.
2045 #if !defined(USE_SYSTEM_ZLIB)
2046 TEST_P(SpdyFramerTest
, CreateSynStreamCompressed
) {
2047 if (!IsSpdy2() && !IsSpdy3()) {
2048 // SYN_STREAM not supported for SPDY>3
2051 SpdyFramer
framer(spdy_version_
);
2052 framer
.set_enable_compression(true);
2055 const char kDescription
[] =
2056 "SYN_STREAM frame, low pri, no FIN";
2057 const SpdyPriority priority
= IsSpdy2() ? 2 : 4;
2059 const unsigned char kV2FrameData
[] = {
2060 0x80, spdy_version_ch_
, 0x00, 0x01,
2061 0x00, 0x00, 0x00, 0x36,
2062 0x00, 0x00, 0x00, 0x01,
2063 0x00, 0x00, 0x00, 0x00,
2064 0x80, 0x00, 0x38, 0xea,
2065 0xdf, 0xa2, 0x51, 0xb2,
2066 0x62, 0x60, 0x62, 0x60,
2067 0x4e, 0x4a, 0x2c, 0x62,
2068 0x60, 0x06, 0x08, 0xa0,
2069 0xb4, 0xfc, 0x7c, 0x80,
2070 0x00, 0x62, 0x60, 0x4e,
2071 0xcb, 0xcf, 0x67, 0x60,
2072 0x06, 0x08, 0xa0, 0xa4,
2073 0xc4, 0x22, 0x80, 0x00,
2074 0x02, 0x00, 0x00, 0x00,
2077 const unsigned char kV3FrameData
[] = {
2078 0x80, spdy_version_ch_
, 0x00, 0x01,
2079 0x00, 0x00, 0x00, 0x37,
2080 0x00, 0x00, 0x00, 0x01,
2081 0x00, 0x00, 0x00, 0x00,
2082 0x80, 0x00, 0x38, 0xEA,
2083 0xE3, 0xC6, 0xA7, 0xC2,
2084 0x02, 0xE5, 0x0E, 0x50,
2085 0xC2, 0x4B, 0x4A, 0x04,
2086 0xE5, 0x0B, 0x66, 0x80,
2087 0x00, 0x4A, 0xCB, 0xCF,
2088 0x07, 0x08, 0x20, 0x10,
2089 0x95, 0x96, 0x9F, 0x0F,
2090 0xA2, 0x00, 0x02, 0x28,
2091 0x29, 0xB1, 0x08, 0x20,
2092 0x80, 0x00, 0x00, 0x00,
2095 const unsigned char kV2SIMDFrameData
[] = {
2096 0x80, spdy_version_ch_
, 0x00, 0x01,
2097 0x00, 0x00, 0x00, 0x33,
2098 0x00, 0x00, 0x00, 0x01,
2099 0x00, 0x00, 0x00, 0x00,
2100 0x80, 0x00, 0x38, 0xea,
2101 0xdf, 0xa2, 0x51, 0xb2,
2102 0x62, 0x60, 0x62, 0x60,
2103 0x4e, 0x4a, 0x2c, 0x62,
2104 0x60, 0x06, 0x08, 0xa0,
2105 0xb4, 0xfc, 0x7c, 0x80,
2106 0x00, 0x62, 0x60, 0x06,
2107 0x13, 0x00, 0x01, 0x94,
2108 0x94, 0x58, 0x04, 0x10,
2109 0x40, 0x00, 0x00, 0x00,
2112 const unsigned char kV3SIMDFrameData
[] = {
2113 0x80, spdy_version_ch_
, 0x00, 0x01,
2114 0x00, 0x00, 0x00, 0x32,
2115 0x00, 0x00, 0x00, 0x01,
2116 0x00, 0x00, 0x00, 0x00,
2117 0x80, 0x00, 0x38, 0xea,
2118 0xe3, 0xc6, 0xa7, 0xc2,
2119 0x02, 0xe5, 0x0e, 0x50,
2120 0xc2, 0x4b, 0x4a, 0x04,
2121 0xe5, 0x0b, 0x66, 0x80,
2122 0x00, 0x4a, 0xcb, 0xcf,
2123 0x07, 0x08, 0x20, 0x24,
2124 0x0a, 0x20, 0x80, 0x92,
2125 0x12, 0x8b, 0x00, 0x02,
2126 0x08, 0x00, 0x00, 0x00,
2130 SpdySynStreamIR
syn_stream(1);
2131 syn_stream
.set_priority(priority
);
2132 syn_stream
.SetHeader("bar", "foo");
2133 syn_stream
.SetHeader("foo", "bar");
2134 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
2135 const unsigned char* frame_data
=
2136 reinterpret_cast<const unsigned char*>(frame
->data());
2138 // Try comparing with SIMD version, if that fails, do a failing check
2139 // with pretty printing against non-SIMD version
2140 if (memcmp(frame_data
,
2142 std::min(arraysize(kV2SIMDFrameData
), frame
->size())) != 0) {
2143 CompareCharArraysWithHexError(kDescription
,
2147 arraysize(kV2FrameData
));
2149 } else if (IsSpdy3()) {
2150 if (memcmp(frame_data
,
2152 std::min(arraysize(kV3SIMDFrameData
), frame
->size())) != 0) {
2153 CompareCharArraysWithHexError(kDescription
,
2157 arraysize(kV3FrameData
));
2160 LOG(FATAL
) << "Unsupported version in test.";
2164 #endif // !defined(USE_SYSTEM_ZLIB)
2166 TEST_P(SpdyFramerTest
, CreateSynReplyUncompressed
) {
2167 if (spdy_version_
> SPDY3
) {
2168 // SYN_REPLY unsupported in SPDY>3
2171 SpdyFramer
framer(spdy_version_
);
2172 framer
.set_enable_compression(false);
2175 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2177 const unsigned char kV2FrameData
[] = {
2178 0x80, spdy_version_ch_
, 0x00, 0x02,
2179 0x00, 0x00, 0x00, 0x1C,
2180 0x00, 0x00, 0x00, 0x01,
2181 0x00, 0x00, 0x00, 0x02,
2182 0x00, 0x03, 'b', 'a',
2183 'r', 0x00, 0x03, 'f',
2184 'o', 'o', 0x00, 0x03,
2185 'f', 'o', 'o', 0x00,
2188 const unsigned char kV3FrameData
[] = {
2189 0x80, spdy_version_ch_
, 0x00, 0x02,
2190 0x00, 0x00, 0x00, 0x24,
2191 0x00, 0x00, 0x00, 0x01,
2192 0x00, 0x00, 0x00, 0x02,
2193 0x00, 0x00, 0x00, 0x03,
2194 'b', 'a', 'r', 0x00,
2195 0x00, 0x00, 0x03, 'f',
2196 'o', 'o', 0x00, 0x00,
2197 0x00, 0x03, 'f', 'o',
2198 'o', 0x00, 0x00, 0x00,
2201 SpdySynReplyIR
syn_reply(1);
2202 syn_reply
.SetHeader("bar", "foo");
2203 syn_reply
.SetHeader("foo", "bar");
2204 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2206 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2207 } else if (IsSpdy3()) {
2208 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2210 LOG(FATAL
) << "Unsupported version in test.";
2215 const char kDescription
[] =
2216 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2218 const unsigned char kV2FrameData
[] = {
2219 0x80, spdy_version_ch_
, 0x00, 0x02,
2220 0x01, 0x00, 0x00, 0x19,
2221 0x7f, 0xff, 0xff, 0xff,
2222 0x00, 0x00, 0x00, 0x02,
2223 0x00, 0x00, 0x00, 0x03,
2224 'f', 'o', 'o', 0x00,
2225 0x03, 'f', 'o', 'o',
2226 0x00, 0x03, 'b', 'a',
2229 const unsigned char kV3FrameData
[] = {
2230 0x80, spdy_version_ch_
, 0x00, 0x02,
2231 0x01, 0x00, 0x00, 0x21,
2232 0x7f, 0xff, 0xff, 0xff,
2233 0x00, 0x00, 0x00, 0x02,
2234 0x00, 0x00, 0x00, 0x00,
2235 0x00, 0x00, 0x00, 0x03,
2236 'f', 'o', 'o', 0x00,
2237 0x00, 0x00, 0x03, 'f',
2238 'o', 'o', 0x00, 0x00,
2239 0x00, 0x03, 'b', 'a',
2242 SpdySynReplyIR
syn_reply(0x7fffffff);
2243 syn_reply
.set_fin(true);
2244 syn_reply
.SetHeader("", "foo");
2245 syn_reply
.SetHeader("foo", "bar");
2246 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2248 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2249 } else if (IsSpdy3()) {
2250 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2252 LOG(FATAL
) << "Unsupported version in test.";
2257 const char kDescription
[] =
2258 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2260 const unsigned char kV2FrameData
[] = {
2261 0x80, spdy_version_ch_
, 0x00, 0x02,
2262 0x01, 0x00, 0x00, 0x19,
2263 0x7f, 0xff, 0xff, 0xff,
2264 0x00, 0x00, 0x00, 0x02,
2265 0x00, 0x03, 'b', 'a',
2266 'r', 0x00, 0x03, 'f',
2267 'o', 'o', 0x00, 0x03,
2268 'f', 'o', 'o', 0x00,
2271 const unsigned char kV3FrameData
[] = {
2272 0x80, spdy_version_ch_
, 0x00, 0x02,
2273 0x01, 0x00, 0x00, 0x21,
2274 0x7f, 0xff, 0xff, 0xff,
2275 0x00, 0x00, 0x00, 0x02,
2276 0x00, 0x00, 0x00, 0x03,
2277 'b', 'a', 'r', 0x00,
2278 0x00, 0x00, 0x03, 'f',
2279 'o', 'o', 0x00, 0x00,
2280 0x00, 0x03, 'f', 'o',
2281 'o', 0x00, 0x00, 0x00,
2284 SpdySynReplyIR
syn_reply(0x7fffffff);
2285 syn_reply
.set_fin(true);
2286 syn_reply
.SetHeader("bar", "foo");
2287 syn_reply
.SetHeader("foo", "");
2288 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2290 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2291 } else if (IsSpdy3()) {
2292 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2294 LOG(FATAL
) << "Unsupported version in test.";
2299 // TODO(phajdan.jr): Clean up after we no longer need
2300 // to workaround http://crbug.com/139744.
2301 #if !defined(USE_SYSTEM_ZLIB)
2302 TEST_P(SpdyFramerTest
, CreateSynReplyCompressed
) {
2303 if (spdy_version_
> SPDY3
) {
2304 // SYN_REPLY unsupported in SPDY>3
2307 SpdyFramer
framer(spdy_version_
);
2308 framer
.set_enable_compression(true);
2311 const char kDescription
[] = "SYN_REPLY frame, no FIN";
2313 const unsigned char kV2FrameData
[] = {
2314 0x80, spdy_version_ch_
, 0x00, 0x02,
2315 0x00, 0x00, 0x00, 0x32,
2316 0x00, 0x00, 0x00, 0x01,
2317 0x00, 0x00, 0x38, 0xea,
2318 0xdf, 0xa2, 0x51, 0xb2,
2319 0x62, 0x60, 0x62, 0x60,
2320 0x4e, 0x4a, 0x2c, 0x62,
2321 0x60, 0x06, 0x08, 0xa0,
2322 0xb4, 0xfc, 0x7c, 0x80,
2323 0x00, 0x62, 0x60, 0x4e,
2324 0xcb, 0xcf, 0x67, 0x60,
2325 0x06, 0x08, 0xa0, 0xa4,
2326 0xc4, 0x22, 0x80, 0x00,
2327 0x02, 0x00, 0x00, 0x00,
2330 const unsigned char kV3FrameData
[] = {
2331 0x80, spdy_version_ch_
, 0x00, 0x02,
2332 0x00, 0x00, 0x00, 0x31,
2333 0x00, 0x00, 0x00, 0x01,
2334 0x38, 0xea, 0xe3, 0xc6,
2335 0xa7, 0xc2, 0x02, 0xe5,
2336 0x0e, 0x50, 0xc2, 0x4b,
2337 0x4a, 0x04, 0xe5, 0x0b,
2338 0x66, 0x80, 0x00, 0x4a,
2339 0xcb, 0xcf, 0x07, 0x08,
2340 0x20, 0x10, 0x95, 0x96,
2341 0x9f, 0x0f, 0xa2, 0x00,
2342 0x02, 0x28, 0x29, 0xb1,
2343 0x08, 0x20, 0x80, 0x00,
2344 0x00, 0x00, 0x00, 0xff,
2347 const unsigned char kV2SIMDFrameData
[] = {
2348 0x80, spdy_version_ch_
, 0x00, 0x02,
2349 0x00, 0x00, 0x00, 0x2f,
2350 0x00, 0x00, 0x00, 0x01,
2351 0x00, 0x00, 0x38, 0xea,
2352 0xdf, 0xa2, 0x51, 0xb2,
2353 0x62, 0x60, 0x62, 0x60,
2354 0x4e, 0x4a, 0x2c, 0x62,
2355 0x60, 0x06, 0x08, 0xa0,
2356 0xb4, 0xfc, 0x7c, 0x80,
2357 0x00, 0x62, 0x60, 0x06,
2358 0x13, 0x00, 0x01, 0x94,
2359 0x94, 0x58, 0x04, 0x10,
2360 0x40, 0x00, 0x00, 0x00,
2363 const unsigned char kV3SIMDFrameData
[] = {
2364 0x80, spdy_version_ch_
, 0x00, 0x02,
2365 0x00, 0x00, 0x00, 0x2c,
2366 0x00, 0x00, 0x00, 0x01,
2367 0x38, 0xea, 0xe3, 0xc6,
2368 0xa7, 0xc2, 0x02, 0xe5,
2369 0x0e, 0x50, 0xc2, 0x4b,
2370 0x4a, 0x04, 0xe5, 0x0b,
2371 0x66, 0x80, 0x00, 0x4a,
2372 0xcb, 0xcf, 0x07, 0x08,
2373 0x20, 0x24, 0x0a, 0x20,
2374 0x80, 0x92, 0x12, 0x8b,
2375 0x00, 0x02, 0x08, 0x00,
2376 0x00, 0x00, 0xff, 0xff,
2379 SpdySynReplyIR
syn_reply(1);
2380 syn_reply
.SetHeader("bar", "foo");
2381 syn_reply
.SetHeader("foo", "bar");
2382 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
2383 const unsigned char* frame_data
=
2384 reinterpret_cast<const unsigned char*>(frame
->data());
2386 // Try comparing with SIMD version, if that fails, do a failing check
2387 // with pretty printing against non-SIMD version
2388 if (memcmp(frame_data
,
2390 std::min(arraysize(kV2SIMDFrameData
), frame
->size())) != 0) {
2391 CompareCharArraysWithHexError(kDescription
,
2395 arraysize(kV2FrameData
));
2397 } else if (IsSpdy3()) {
2398 if (memcmp(frame_data
,
2400 std::min(arraysize(kV3SIMDFrameData
), frame
->size())) != 0) {
2401 CompareCharArraysWithHexError(kDescription
,
2405 arraysize(kV3FrameData
));
2408 LOG(FATAL
) << "Unsupported version in test.";
2412 #endif // !defined(USE_SYSTEM_ZLIB)
2414 TEST_P(SpdyFramerTest
, CreateRstStream
) {
2415 SpdyFramer
framer(spdy_version_
);
2418 const char kDescription
[] = "RST_STREAM frame";
2419 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2420 0x80, spdy_version_ch_
, 0x00, 0x03,
2421 0x00, 0x00, 0x00, 0x08,
2422 0x00, 0x00, 0x00, 0x01,
2423 0x00, 0x00, 0x00, 0x01,
2425 const unsigned char kV4FrameData
[] = {
2426 0x00, 0x00, 0x07, 0x03,
2427 0x00, 0x00, 0x00, 0x00,
2428 0x01, 0x00, 0x00, 0x00,
2429 0x01, 0x52, 0x53, 0x54
2431 SpdyRstStreamIR
rst_stream(1, RST_STREAM_PROTOCOL_ERROR
, "RST");
2432 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2434 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2436 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2441 const char kDescription
[] = "RST_STREAM frame with max stream ID";
2442 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2443 0x80, spdy_version_ch_
, 0x00, 0x03,
2444 0x00, 0x00, 0x00, 0x08,
2445 0x7f, 0xff, 0xff, 0xff,
2446 0x00, 0x00, 0x00, 0x01,
2448 const unsigned char kV4FrameData
[] = {
2449 0x00, 0x00, 0x04, 0x03,
2450 0x00, 0x7f, 0xff, 0xff,
2451 0xff, 0x00, 0x00, 0x00,
2454 SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2455 RST_STREAM_PROTOCOL_ERROR
,
2457 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2459 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2461 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2466 const char kDescription
[] = "RST_STREAM frame with max status code";
2467 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2468 0x80, spdy_version_ch_
, 0x00, 0x03,
2469 0x00, 0x00, 0x00, 0x08,
2470 0x7f, 0xff, 0xff, 0xff,
2471 0x00, 0x00, 0x00, 0x06,
2473 const unsigned char kV4FrameData
[] = {
2474 0x00, 0x00, 0x04, 0x03,
2475 0x00, 0x7f, 0xff, 0xff,
2476 0xff, 0x00, 0x00, 0x00,
2479 SpdyRstStreamIR
rst_stream(0x7FFFFFFF,
2480 RST_STREAM_INTERNAL_ERROR
,
2482 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
2484 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2486 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2491 TEST_P(SpdyFramerTest
, CreateSettings
) {
2492 SpdyFramer
framer(spdy_version_
);
2495 const char kDescription
[] = "Network byte order SETTINGS frame";
2497 const unsigned char kV2FrameData
[] = {
2498 0x80, spdy_version_ch_
, 0x00, 0x04,
2499 0x00, 0x00, 0x00, 0x0c,
2500 0x00, 0x00, 0x00, 0x01,
2501 0x07, 0x00, 0x00, 0x01,
2502 0x0a, 0x0b, 0x0c, 0x0d,
2504 const unsigned char kV3FrameData
[] = {
2505 0x80, spdy_version_ch_
, 0x00, 0x04,
2506 0x00, 0x00, 0x00, 0x0c,
2507 0x00, 0x00, 0x00, 0x01,
2508 0x01, 0x00, 0x00, 0x07,
2509 0x0a, 0x0b, 0x0c, 0x0d,
2511 const unsigned char kV4FrameData
[] = {
2512 0x00, 0x00, 0x06, 0x04,
2513 0x00, 0x00, 0x00, 0x00,
2514 0x00, 0x00, 0x04, 0x0a,
2518 uint32 kValue
= 0x0a0b0c0d;
2519 SpdySettingsIR settings_ir
;
2521 SpdySettingsFlags kFlags
= static_cast<SpdySettingsFlags
>(0x01);
2522 SpdySettingsIds kId
= SETTINGS_INITIAL_WINDOW_SIZE
;
2523 settings_ir
.AddSetting(kId
,
2524 kFlags
& SETTINGS_FLAG_PLEASE_PERSIST
,
2525 kFlags
& SETTINGS_FLAG_PERSISTED
,
2528 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2530 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2531 } else if (IsSpdy3()) {
2532 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2534 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2539 const char kDescription
[] = "Basic SETTINGS frame";
2541 const unsigned char kV2FrameData
[] = {
2542 0x80, spdy_version_ch_
, 0x00, 0x04,
2543 0x00, 0x00, 0x00, 0x24,
2544 0x00, 0x00, 0x00, 0x04,
2545 0x01, 0x00, 0x00, 0x00, // 1st Setting
2546 0x00, 0x00, 0x00, 0x05,
2547 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2548 0x00, 0x00, 0x00, 0x06,
2549 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2550 0x00, 0x00, 0x00, 0x07,
2551 0x04, 0x00, 0x00, 0x00, // 4th Setting
2552 0x00, 0x00, 0x00, 0x08,
2554 const unsigned char kV3FrameData
[] = {
2555 0x80, spdy_version_ch_
, 0x00, 0x04,
2556 0x00, 0x00, 0x00, 0x24,
2557 0x00, 0x00, 0x00, 0x04,
2558 0x00, 0x00, 0x00, 0x01, // 1st Setting
2559 0x00, 0x00, 0x00, 0x05,
2560 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2561 0x00, 0x00, 0x00, 0x06,
2562 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2563 0x00, 0x00, 0x00, 0x07,
2564 0x00, 0x00, 0x00, 0x04, // 4th Setting
2565 0x00, 0x00, 0x00, 0x08,
2567 // These end up seemingly out of order because of the way that our internal
2568 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2570 const unsigned char kV4FrameData
[] = {
2571 0x00, 0x00, 0x18, 0x04,
2572 0x00, 0x00, 0x00, 0x00,
2573 0x00, 0x00, 0x03, // 3rd Setting
2574 0x00, 0x00, 0x00, 0x07,
2575 0x00, 0x04, // 4th Setting
2576 0x00, 0x00, 0x00, 0x08,
2577 0x00, 0x01, // 1st Setting
2578 0x00, 0x00, 0x00, 0x05,
2579 0x00, 0x02, // 2nd Setting
2580 0x00, 0x00, 0x00, 0x06,
2583 SpdySettingsIR settings_ir
;
2584 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
2588 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 2),
2592 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 3),
2596 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 4),
2600 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2603 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2604 } else if (IsSpdy3()) {
2605 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2607 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2612 const char kDescription
[] = "Empty SETTINGS frame";
2614 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2615 0x80, spdy_version_ch_
, 0x00, 0x04,
2616 0x00, 0x00, 0x00, 0x04,
2617 0x00, 0x00, 0x00, 0x00,
2619 const unsigned char kV4FrameData
[] = {
2620 0x00, 0x00, 0x00, 0x04,
2621 0x00, 0x00, 0x00, 0x00,
2624 SpdySettingsIR settings_ir
;
2625 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
2627 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2629 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2634 TEST_P(SpdyFramerTest
, CreatePingFrame
) {
2635 SpdyFramer
framer(spdy_version_
);
2638 const char kDescription
[] = "PING frame";
2639 const unsigned char kV3FrameData
[] = { // Also applies for V2.
2640 0x80, spdy_version_ch_
, 0x00, 0x06,
2641 0x00, 0x00, 0x00, 0x04,
2642 0x12, 0x34, 0x56, 0x78,
2644 const unsigned char kV4FrameData
[] = {
2645 0x00, 0x00, 0x08, 0x06,
2646 0x00, 0x00, 0x00, 0x00,
2647 0x00, 0x12, 0x34, 0x56,
2648 0x78, 0x9a, 0xbc, 0xde,
2651 const unsigned char kV4FrameDataWithAck
[] = {
2652 0x00, 0x00, 0x08, 0x06,
2653 0x01, 0x00, 0x00, 0x00,
2654 0x00, 0x12, 0x34, 0x56,
2655 0x78, 0x9a, 0xbc, 0xde,
2658 scoped_ptr
<SpdyFrame
> frame
;
2660 const SpdyPingId kPingId
= 0x123456789abcdeffULL
;
2661 SpdyPingIR
ping_ir(kPingId
);
2662 // Tests SpdyPingIR when the ping is not an ack.
2663 ASSERT_FALSE(ping_ir
.is_ack());
2664 frame
.reset(framer
.SerializePing(ping_ir
));
2665 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2667 // Tests SpdyPingIR when the ping is an ack.
2668 ping_ir
.set_is_ack(true);
2669 frame
.reset(framer
.SerializePing(ping_ir
));
2670 CompareFrame(kDescription
, *frame
,
2671 kV4FrameDataWithAck
, arraysize(kV4FrameDataWithAck
));
2674 frame
.reset(framer
.SerializePing(SpdyPingIR(0x12345678ull
)));
2675 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2680 TEST_P(SpdyFramerTest
, CreateGoAway
) {
2681 SpdyFramer
framer(spdy_version_
);
2684 const char kDescription
[] = "GOAWAY frame";
2685 const unsigned char kV2FrameData
[] = {
2686 0x80, spdy_version_ch_
, 0x00, 0x07,
2687 0x00, 0x00, 0x00, 0x04,
2688 0x00, 0x00, 0x00, 0x00, // Stream Id
2690 const unsigned char kV3FrameData
[] = {
2691 0x80, spdy_version_ch_
, 0x00, 0x07,
2692 0x00, 0x00, 0x00, 0x08,
2693 0x00, 0x00, 0x00, 0x00, // Stream Id
2694 0x00, 0x00, 0x00, 0x00, // Status
2696 const unsigned char kV4FrameData
[] = {
2697 0x00, 0x00, 0x0a, 0x07,
2698 0x00, 0x00, 0x00, 0x00,
2699 0x00, 0x00, 0x00, 0x00, // Stream id
2700 0x00, 0x00, 0x00, 0x00, // Status
2701 0x00, 0x47, 0x41, // Opaque Description
2703 SpdyGoAwayIR
goaway_ir(0, GOAWAY_OK
, "GA");
2704 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2706 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2707 } else if (IsSpdy3()) {
2708 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2710 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2715 const char kDescription
[] = "GOAWAY frame with max stream ID, status";
2716 const unsigned char kV2FrameData
[] = {
2717 0x80, spdy_version_ch_
, 0x00, 0x07,
2718 0x00, 0x00, 0x00, 0x04,
2719 0x7f, 0xff, 0xff, 0xff, // Stream Id
2721 const unsigned char kV3FrameData
[] = {
2722 0x80, spdy_version_ch_
, 0x00, 0x07,
2723 0x00, 0x00, 0x00, 0x08,
2724 0x7f, 0xff, 0xff, 0xff, // Stream Id
2725 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2727 const unsigned char kV4FrameData
[] = {
2728 0x00, 0x00, 0x0a, 0x07,
2729 0x00, 0x00, 0x00, 0x00,
2730 0x00, 0x7f, 0xff, 0xff, // Stream Id
2731 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2732 0x02, 0x47, 0x41, // Opaque Description
2734 SpdyGoAwayIR
goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR
, "GA");
2735 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
2737 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2738 } else if (IsSpdy3()) {
2739 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2741 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2746 TEST_P(SpdyFramerTest
, CreateHeadersUncompressed
) {
2747 SpdyFramer
framer(spdy_version_
);
2748 framer
.set_enable_compression(false);
2751 const char kDescription
[] = "HEADERS frame, no FIN";
2753 const unsigned char kV2FrameData
[] = {
2754 0x80, spdy_version_ch_
, 0x00, 0x08,
2755 0x00, 0x00, 0x00, 0x1C,
2756 0x00, 0x00, 0x00, 0x01,
2757 0x00, 0x00, 0x00, 0x02,
2758 0x00, 0x03, 'b', 'a',
2759 'r', 0x00, 0x03, 'f',
2760 'o', 'o', 0x00, 0x03,
2761 'f', 'o', 'o', 0x00,
2764 const unsigned char kV3FrameData
[] = {
2765 0x80, spdy_version_ch_
, 0x00, 0x08,
2766 0x00, 0x00, 0x00, 0x24,
2767 0x00, 0x00, 0x00, 0x01,
2768 0x00, 0x00, 0x00, 0x02,
2769 0x00, 0x00, 0x00, 0x03,
2770 'b', 'a', 'r', 0x00,
2771 0x00, 0x00, 0x03, 'f',
2772 'o', 'o', 0x00, 0x00,
2773 0x00, 0x03, 'f', 'o',
2774 'o', 0x00, 0x00, 0x00,
2777 const unsigned char kV4FrameData
[] = {
2778 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2779 0x04, 0x00, 0x00, 0x00, // Stream 1
2780 0x01, 0x00, 0x03, 0x62, // @.ba
2781 0x61, 0x72, 0x03, 0x66, // r.fo
2782 0x6f, 0x6f, 0x00, 0x03, // o@.f
2783 0x66, 0x6f, 0x6f, 0x03, // oo.b
2784 0x62, 0x61, 0x72, // ar
2786 SpdyHeadersIR
headers_ir(1);
2787 headers_ir
.SetHeader("bar", "foo");
2788 headers_ir
.SetHeader("foo", "bar");
2789 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2791 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2792 } else if (IsSpdy3()) {
2793 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2795 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2800 const char kDescription
[] =
2801 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2803 const unsigned char kV2FrameData
[] = {
2804 0x80, spdy_version_ch_
, 0x00, 0x08,
2805 0x01, 0x00, 0x00, 0x19,
2806 0x7f, 0xff, 0xff, 0xff,
2807 0x00, 0x00, 0x00, 0x02,
2808 0x00, 0x00, 0x00, 0x03,
2809 'f', 'o', 'o', 0x00,
2810 0x03, 'f', 'o', 'o',
2811 0x00, 0x03, 'b', 'a',
2814 const unsigned char kV3FrameData
[] = {
2815 0x80, spdy_version_ch_
, 0x00, 0x08,
2816 0x01, 0x00, 0x00, 0x21,
2817 0x7f, 0xff, 0xff, 0xff,
2818 0x00, 0x00, 0x00, 0x02,
2819 0x00, 0x00, 0x00, 0x00,
2820 0x00, 0x00, 0x00, 0x03,
2821 'f', 'o', 'o', 0x00,
2822 0x00, 0x00, 0x03, 'f',
2823 'o', 'o', 0x00, 0x00,
2824 0x00, 0x03, 'b', 'a',
2827 const unsigned char kV4FrameData
[] = {
2828 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2829 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2830 0xff, 0x00, 0x00, 0x03, // @..
2831 0x66, 0x6f, 0x6f, 0x00, // foo@
2832 0x03, 0x66, 0x6f, 0x6f, // .foo
2833 0x03, 0x62, 0x61, 0x72, // .bar
2835 SpdyHeadersIR
headers_ir(0x7fffffff);
2836 headers_ir
.set_fin(true);
2837 headers_ir
.SetHeader("", "foo");
2838 headers_ir
.SetHeader("foo", "bar");
2839 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2841 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2842 } else if (IsSpdy3()) {
2843 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2845 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2850 const char kDescription
[] =
2851 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2853 const unsigned char kV2FrameData
[] = {
2854 0x80, spdy_version_ch_
, 0x00, 0x08,
2855 0x01, 0x00, 0x00, 0x19,
2856 0x7f, 0xff, 0xff, 0xff,
2857 0x00, 0x00, 0x00, 0x02,
2858 0x00, 0x03, 'b', 'a',
2859 'r', 0x00, 0x03, 'f',
2860 'o', 'o', 0x00, 0x03,
2861 'f', 'o', 'o', 0x00,
2864 const unsigned char kV3FrameData
[] = {
2865 0x80, spdy_version_ch_
, 0x00, 0x08,
2866 0x01, 0x00, 0x00, 0x21,
2867 0x7f, 0xff, 0xff, 0xff,
2868 0x00, 0x00, 0x00, 0x02,
2869 0x00, 0x00, 0x00, 0x03,
2870 'b', 'a', 'r', 0x00,
2871 0x00, 0x00, 0x03, 'f',
2872 'o', 'o', 0x00, 0x00,
2873 0x00, 0x03, 'f', 'o',
2874 'o', 0x00, 0x00, 0x00,
2877 const unsigned char kV4FrameData
[] = {
2878 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2879 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2880 0xff, 0x00, 0x03, 0x62, // @.b
2881 0x61, 0x72, 0x03, 0x66, // ar.f
2882 0x6f, 0x6f, 0x00, 0x03, // oo@.
2883 0x66, 0x6f, 0x6f, 0x00, // foo.
2885 SpdyHeadersIR
headers_ir(0x7fffffff);
2886 headers_ir
.set_fin(true);
2887 headers_ir
.SetHeader("bar", "foo");
2888 headers_ir
.SetHeader("foo", "");
2889 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2891 CompareFrame(kDescription
, *frame
, kV2FrameData
, arraysize(kV2FrameData
));
2892 } else if (IsSpdy3()) {
2893 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
2895 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2900 const char kDescription
[] =
2901 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2903 const unsigned char kV4FrameData
[] = {
2904 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2905 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2906 0xff, 0x00, 0x00, 0x00, // parent stream
2907 0x00, 0xdb, // weight
2908 0x00, 0x03, 0x62, 0x61, // @.ba
2909 0x72, 0x03, 0x66, 0x6f, // r.fo
2910 0x6f, 0x00, 0x03, 0x66, // o@.f
2911 0x6f, 0x6f, 0x00, // oo.
2913 SpdyHeadersIR
headers_ir(0x7fffffff);
2914 headers_ir
.set_fin(true);
2915 headers_ir
.set_priority(1);
2916 headers_ir
.set_has_priority(true);
2917 headers_ir
.SetHeader("bar", "foo");
2918 headers_ir
.SetHeader("foo", "");
2919 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2920 if (IsSpdy2() || IsSpdy3()) {
2921 // HEADERS with priority not supported.
2923 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2928 const char kDescription
[] =
2929 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2931 const unsigned char kV4FrameData
[] = {
2932 0x00, 0x00, 0x15, 0x01, // Headers
2933 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2935 0xff, 0x05, 0x00, 0x00, // Pad length field
2936 0x03, 0x66, 0x6f, 0x6f, // .foo
2937 0x00, 0x03, 0x66, 0x6f, // @.fo
2938 0x6f, 0x03, 0x62, 0x61, // o.ba
2941 0x00, 0x00, 0x00, 0x00, 0x00,
2943 SpdyHeadersIR
headers_ir(0x7fffffff);
2944 headers_ir
.set_fin(true);
2945 headers_ir
.SetHeader("", "foo");
2946 headers_ir
.SetHeader("foo", "bar");
2947 headers_ir
.set_padding_len(6);
2948 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
2949 if (IsSpdy2() || IsSpdy3()) {
2950 // Padding is not supported.
2952 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
2957 // TODO(phajdan.jr): Clean up after we no longer need
2958 // to workaround http://crbug.com/139744.
2959 #if !defined(USE_SYSTEM_ZLIB)
2960 TEST_P(SpdyFramerTest
, CreateHeadersCompressed
) {
2961 SpdyFramer
framer(spdy_version_
);
2962 framer
.set_enable_compression(true);
2965 const char kDescription
[] = "HEADERS frame, no FIN";
2967 const unsigned char kV2FrameData
[] = {
2968 0x80, spdy_version_ch_
, 0x00, 0x08,
2969 0x00, 0x00, 0x00, 0x32,
2970 0x00, 0x00, 0x00, 0x01,
2971 0x00, 0x00, 0x38, 0xea,
2972 0xdf, 0xa2, 0x51, 0xb2,
2973 0x62, 0x60, 0x62, 0x60,
2974 0x4e, 0x4a, 0x2c, 0x62,
2975 0x60, 0x06, 0x08, 0xa0,
2976 0xb4, 0xfc, 0x7c, 0x80,
2977 0x00, 0x62, 0x60, 0x4e,
2978 0xcb, 0xcf, 0x67, 0x60,
2979 0x06, 0x08, 0xa0, 0xa4,
2980 0xc4, 0x22, 0x80, 0x00,
2981 0x02, 0x00, 0x00, 0x00,
2984 const unsigned char kV3FrameData
[] = {
2985 0x80, spdy_version_ch_
, 0x00, 0x08,
2986 0x00, 0x00, 0x00, 0x31,
2987 0x00, 0x00, 0x00, 0x01,
2988 0x38, 0xea, 0xe3, 0xc6,
2989 0xa7, 0xc2, 0x02, 0xe5,
2990 0x0e, 0x50, 0xc2, 0x4b,
2991 0x4a, 0x04, 0xe5, 0x0b,
2992 0x66, 0x80, 0x00, 0x4a,
2993 0xcb, 0xcf, 0x07, 0x08,
2994 0x20, 0x10, 0x95, 0x96,
2995 0x9f, 0x0f, 0xa2, 0x00,
2996 0x02, 0x28, 0x29, 0xb1,
2997 0x08, 0x20, 0x80, 0x00,
2998 0x00, 0x00, 0x00, 0xff,
3001 const unsigned char kV2SIMDFrameData
[] = {
3002 0x80, spdy_version_ch_
, 0x00, 0x08,
3003 0x00, 0x00, 0x00, 0x2f,
3004 0x00, 0x00, 0x00, 0x01,
3005 0x00, 0x00, 0x38, 0xea,
3006 0xdf, 0xa2, 0x51, 0xb2,
3007 0x62, 0x60, 0x62, 0x60,
3008 0x4e, 0x4a, 0x2c, 0x62,
3009 0x60, 0x06, 0x08, 0xa0,
3010 0xb4, 0xfc, 0x7c, 0x80,
3011 0x00, 0x62, 0x60, 0x06,
3012 0x13, 0x00, 0x01, 0x94,
3013 0x94, 0x58, 0x04, 0x10,
3014 0x40, 0x00, 0x00, 0x00,
3017 const unsigned char kV3SIMDFrameData
[] = {
3018 0x80, spdy_version_ch_
, 0x00, 0x08,
3019 0x00, 0x00, 0x00, 0x2c,
3020 0x00, 0x00, 0x00, 0x01,
3021 0x38, 0xea, 0xe3, 0xc6,
3022 0xa7, 0xc2, 0x02, 0xe5,
3023 0x0e, 0x50, 0xc2, 0x4b,
3024 0x4a, 0x04, 0xe5, 0x0b,
3025 0x66, 0x80, 0x00, 0x4a,
3026 0xcb, 0xcf, 0x07, 0x08,
3027 0x20, 0x24, 0x0a, 0x20,
3028 0x80, 0x92, 0x12, 0x8b,
3029 0x00, 0x02, 0x08, 0x00,
3030 0x00, 0x00, 0xff, 0xff,
3033 SpdyHeadersIR
headers_ir(1);
3034 headers_ir
.SetHeader("bar", "foo");
3035 headers_ir
.SetHeader("foo", "bar");
3036 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
3037 const unsigned char* frame_data
=
3038 reinterpret_cast<const unsigned char*>(frame
->data());
3040 // Try comparing with SIMD version, if that fails, do a failing check
3041 // with pretty printing against non-SIMD version
3042 if (memcmp(frame_data
,
3044 std::min(arraysize(kV2SIMDFrameData
), frame
->size())) != 0) {
3045 CompareCharArraysWithHexError(kDescription
,
3049 arraysize(kV2FrameData
));
3051 } else if (IsSpdy3()) {
3052 if (memcmp(frame_data
,
3054 std::min(arraysize(kV3SIMDFrameData
), frame
->size())) != 0) {
3055 CompareCharArraysWithHexError(kDescription
,
3059 arraysize(kV3FrameData
));
3062 // Deflate compression doesn't apply to HPACK.
3066 #endif // !defined(USE_SYSTEM_ZLIB)
3068 TEST_P(SpdyFramerTest
, CreateWindowUpdate
) {
3069 SpdyFramer
framer(spdy_version_
);
3072 const char kDescription
[] = "WINDOW_UPDATE frame";
3073 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3074 0x80, spdy_version_ch_
, 0x00, 0x09,
3075 0x00, 0x00, 0x00, 0x08,
3076 0x00, 0x00, 0x00, 0x01,
3077 0x00, 0x00, 0x00, 0x01,
3079 const unsigned char kV4FrameData
[] = {
3080 0x00, 0x00, 0x04, 0x08,
3081 0x00, 0x00, 0x00, 0x00,
3082 0x01, 0x00, 0x00, 0x00,
3085 scoped_ptr
<SpdyFrame
> frame(
3086 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3088 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
3090 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
3095 const char kDescription
[] = "WINDOW_UPDATE frame with max stream ID";
3096 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3097 0x80, spdy_version_ch_
, 0x00, 0x09,
3098 0x00, 0x00, 0x00, 0x08,
3099 0x7f, 0xff, 0xff, 0xff,
3100 0x00, 0x00, 0x00, 0x01,
3102 const unsigned char kV4FrameData
[] = {
3103 0x00, 0x00, 0x04, 0x08,
3104 0x00, 0x7f, 0xff, 0xff,
3105 0xff, 0x00, 0x00, 0x00,
3108 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
3109 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3111 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
3113 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
3118 const char kDescription
[] = "WINDOW_UPDATE frame with max window delta";
3119 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3120 0x80, spdy_version_ch_
, 0x00, 0x09,
3121 0x00, 0x00, 0x00, 0x08,
3122 0x00, 0x00, 0x00, 0x01,
3123 0x7f, 0xff, 0xff, 0xff,
3125 const unsigned char kV4FrameData
[] = {
3126 0x00, 0x00, 0x04, 0x08,
3127 0x00, 0x00, 0x00, 0x00,
3128 0x01, 0x7f, 0xff, 0xff,
3131 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
3132 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3134 CompareFrame(kDescription
, *frame
, kV4FrameData
, arraysize(kV4FrameData
));
3136 CompareFrame(kDescription
, *frame
, kV3FrameData
, arraysize(kV3FrameData
));
3141 TEST_P(SpdyFramerTest
, SerializeBlocked
) {
3142 if (spdy_version_
<= SPDY3
) {
3146 SpdyFramer
framer(spdy_version_
);
3148 const char kDescription
[] = "BLOCKED frame";
3149 const unsigned char kType
= static_cast<unsigned char>(
3150 SpdyConstants::SerializeFrameType(spdy_version_
, BLOCKED
));
3151 const unsigned char kFrameData
[] = {
3152 0x00, 0x00, 0x00, kType
, 0x00,
3153 0x00, 0x00, 0x00, 0x00,
3155 SpdyBlockedIR
blocked_ir(0);
3156 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
3157 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3160 TEST_P(SpdyFramerTest
, CreateBlocked
) {
3161 if (spdy_version_
<= SPDY3
) {
3165 SpdyFramer
framer(spdy_version_
);
3167 const char kDescription
[] = "BLOCKED frame";
3168 const SpdyStreamId kStreamId
= 3;
3170 scoped_ptr
<SpdySerializedFrame
> frame_serialized(
3171 framer
.SerializeBlocked(SpdyBlockedIR(kStreamId
)));
3172 SpdyBlockedIR
blocked_ir(kStreamId
);
3173 scoped_ptr
<SpdySerializedFrame
> frame_created(
3174 framer
.SerializeFrame(blocked_ir
));
3176 CompareFrames(kDescription
, *frame_serialized
, *frame_created
);
3179 TEST_P(SpdyFramerTest
, CreatePushPromiseUncompressed
) {
3180 if (spdy_version_
<= SPDY3
) {
3185 // Test framing PUSH_PROMISE without padding.
3186 SpdyFramer
framer(spdy_version_
);
3187 framer
.set_enable_compression(false);
3188 const char kDescription
[] = "PUSH_PROMISE frame without padding";
3190 const unsigned char kFrameData
[] = {
3191 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3192 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3193 0x2a, 0x00, 0x00, 0x00, // Stream 42
3194 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3195 0x61, 0x72, 0x03, 0x66, // ar.f
3196 0x6f, 0x6f, 0x00, 0x03, // oo@.
3197 0x66, 0x6f, 0x6f, 0x03, // foo.
3198 0x62, 0x61, 0x72, // bar
3201 SpdyPushPromiseIR
push_promise(42, 57);
3202 push_promise
.SetHeader("bar", "foo");
3203 push_promise
.SetHeader("foo", "bar");
3204 scoped_ptr
<SpdySerializedFrame
> frame(
3205 framer
.SerializePushPromise(push_promise
));
3206 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3210 // Test framing PUSH_PROMISE with one byte of padding.
3211 SpdyFramer
framer(spdy_version_
);
3212 framer
.set_enable_compression(false);
3213 const char kDescription
[] = "PUSH_PROMISE frame with one byte of padding";
3215 const unsigned char kFrameData
[] = {
3216 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3217 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3218 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3219 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3220 0x62, 0x61, 0x72, 0x03, // bar.
3221 0x66, 0x6f, 0x6f, 0x00, // foo@
3222 0x03, 0x66, 0x6f, 0x6f, // .foo
3223 0x03, 0x62, 0x61, 0x72, // .bar
3226 SpdyPushPromiseIR
push_promise(42, 57);
3227 push_promise
.set_padding_len(1);
3228 push_promise
.SetHeader("bar", "foo");
3229 push_promise
.SetHeader("foo", "bar");
3230 scoped_ptr
<SpdySerializedFrame
> frame(
3231 framer
.SerializePushPromise(push_promise
));
3232 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3236 // Test framing PUSH_PROMISE with 177 bytes of padding.
3237 SpdyFramer
framer(spdy_version_
);
3238 framer
.set_enable_compression(false);
3239 const char kDescription
[] = "PUSH_PROMISE frame with 177 bytes of padding";
3241 const unsigned char kFrameData
[] = {
3242 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3243 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3244 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3245 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3246 0x62, 0x61, 0x72, 0x03, // bar.
3247 0x66, 0x6f, 0x6f, 0x00, // foo@
3248 0x03, 0x66, 0x6f, 0x6f, // .foo
3249 0x03, 0x62, 0x61, 0x72, // .bar
3250 // Padding of 176 0x00(s).
3251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
3268 SpdyPushPromiseIR
push_promise(42, 57);
3269 push_promise
.set_padding_len(177);
3270 push_promise
.SetHeader("bar", "foo");
3271 push_promise
.SetHeader("foo", "bar");
3272 scoped_ptr
<SpdySerializedFrame
> frame(
3273 framer
.SerializePushPromise(push_promise
));
3274 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3278 TEST_P(SpdyFramerTest
, GetNumberRequiredContinuationFrames
) {
3279 if (spdy_version_
<= SPDY3
) {
3283 SpdyFramer
framer(spdy_version_
);
3284 // Test case from https://crbug.com/464748.
3285 EXPECT_EQ(1u, framer
.GetNumberRequiredContinuationFrames(2039));
3286 EXPECT_EQ(2u, framer
.GetNumberRequiredContinuationFrames(2040));
3289 TEST_P(SpdyFramerTest
, CreateContinuationUncompressed
) {
3290 if (spdy_version_
<= SPDY3
) {
3294 SpdyFramer
framer(spdy_version_
);
3295 framer
.set_enable_compression(false);
3296 const char kDescription
[] = "CONTINUATION frame";
3298 const unsigned char kFrameData
[] = {
3299 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3300 0x04, 0x00, 0x00, 0x00, // end_headers = true
3301 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3302 0x61, 0x72, 0x03, 0x66, // ar.f
3303 0x6f, 0x6f, 0x00, 0x03, // oo@.
3304 0x66, 0x6f, 0x6f, 0x03, // foo.
3305 0x62, 0x61, 0x72, // bar
3308 SpdyContinuationIR
continuation(42);
3309 continuation
.SetHeader("bar", "foo");
3310 continuation
.SetHeader("foo", "bar");
3311 continuation
.set_end_headers(true);
3312 scoped_ptr
<SpdySerializedFrame
> frame(
3313 framer
.SerializeContinuation(continuation
));
3314 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3317 TEST_P(SpdyFramerTest
, CreatePushPromiseThenContinuationUncompressed
) {
3318 if (spdy_version_
<= SPDY3
) {
3323 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3324 // padding, cannot hold all the data payload, which is overflowed to the
3325 // consecutive CONTINUATION frame.
3326 SpdyFramer
framer(spdy_version_
);
3327 framer
.set_enable_compression(false);
3328 const char kDescription
[] =
3329 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3331 const unsigned char kPartialPushPromiseFrameData
[] = {
3332 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3333 0x08, 0x00, 0x00, 0x00, // PADDED
3334 0x2a, 0x00, 0x00, 0x00, // Stream 42
3335 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3336 0x78, 0x78, 0x78, 0x7f, // xxx.
3337 0x81, 0x07, 0x78, 0x78, // ..xx
3338 0x78, 0x78, 0x78, 0x78, // xxxx
3339 0x78, 0x78, 0x78, 0x78, // xxxx
3340 0x78, 0x78, 0x78, 0x78, // xxxx
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
3361 const unsigned char kContinuationFrameData
[] = {
3362 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3363 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3364 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3365 0x78, 0x78, 0x78, 0x78, // xxxx
3366 0x78, 0x78, 0x78, 0x78, // xxxx
3367 0x78, 0x78, 0x78, 0x78, // xxxx
3368 0x78, 0x78, 0x78, 0x78, // xxxx
3372 SpdyPushPromiseIR
push_promise(42, 57);
3373 push_promise
.set_padding_len(1);
3374 string
big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3375 push_promise
.SetHeader("xxx", big_value
);
3376 scoped_ptr
<SpdySerializedFrame
> frame(
3377 framer
.SerializePushPromise(push_promise
));
3379 // The entire frame should look like below:
3380 // Name Length in Byte
3381 // ------------------------------------------- Begin of PUSH_PROMISE frame
3382 // PUSH_PROMISE header 9
3383 // Pad length field 1
3384 // Promised stream 4
3385 // Length field of key 2
3387 // Length field of value 3
3388 // Part of big_value 16361
3389 // ------------------------------------------- Begin of CONTINUATION frame
3390 // CONTINUATION header 9
3391 // Remaining of big_value 22
3392 // ------------------------------------------- End
3394 // Length of everything listed above except big_value.
3395 int len_non_data_payload
= 31;
3397 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload
,
3400 // Partially compare the PUSH_PROMISE frame against the template.
3401 const unsigned char* frame_data
=
3402 reinterpret_cast<const unsigned char*>(frame
->data());
3403 CompareCharArraysWithHexError(kDescription
,
3405 arraysize(kPartialPushPromiseFrameData
),
3406 kPartialPushPromiseFrameData
,
3407 arraysize(kPartialPushPromiseFrameData
));
3409 // Compare the CONTINUATION frame against the template.
3410 frame_data
+= TestSpdyVisitor::sent_control_frame_max_size();
3411 CompareCharArraysWithHexError(kDescription
,
3413 arraysize(kContinuationFrameData
),
3414 kContinuationFrameData
,
3415 arraysize(kContinuationFrameData
));
3419 TEST_P(SpdyFramerTest
, CreateAltSvc
) {
3420 if (spdy_version_
<= SPDY3
) {
3424 SpdyFramer
framer(spdy_version_
);
3426 const char kDescription
[] = "ALTSVC frame";
3427 const unsigned char kType
= static_cast<unsigned char>(
3428 SpdyConstants::SerializeFrameType(spdy_version_
, ALTSVC
));
3429 const unsigned char kFrameData
[] = {
3430 0x00, 0x00, 0x17, kType
, 0x00,
3431 0x00, 0x00, 0x00, 0x03,
3432 0x00, 0x00, 0x00, 0x05,
3433 0x01, 0xbb, 0x00, 0x04, // Port = 443
3434 'p', 'i', 'd', '1', // Protocol-ID
3435 0x04, 'h', 'o', 's',
3439 SpdyAltSvcIR
altsvc_ir(3);
3440 altsvc_ir
.set_max_age(5);
3441 altsvc_ir
.set_port(443);
3442 altsvc_ir
.set_protocol_id("pid1");
3443 altsvc_ir
.set_host("host");
3444 altsvc_ir
.set_origin("origin");
3445 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
3446 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3449 TEST_P(SpdyFramerTest
, CreatePriority
) {
3450 if (spdy_version_
<= SPDY3
) {
3454 SpdyFramer
framer(spdy_version_
);
3456 const char kDescription
[] = "PRIORITY frame";
3457 const unsigned char kType
= static_cast<unsigned char>(
3458 SpdyConstants::SerializeFrameType(spdy_version_
, PRIORITY
));
3459 const unsigned char kFrameData
[] = {
3460 0x00, 0x00, 0x05, kType
, 0x00,
3461 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3462 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3463 0x10, // Weight = 16
3465 SpdyPriorityIR
priority_ir(2, 1, 16, true);
3466 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(priority_ir
));
3467 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3468 SpdyPriorityIR
priority2(2);
3469 priority2
.set_parent_stream_id(1);
3470 priority2
.set_weight(16);
3471 priority2
.set_exclusive(true);
3472 frame
.reset(framer
.SerializeFrame(priority2
));
3473 CompareFrame(kDescription
, *frame
, kFrameData
, arraysize(kFrameData
));
3476 TEST_P(SpdyFramerTest
, ReadCompressedSynStreamHeaderBlock
) {
3477 if (spdy_version_
> SPDY3
) {
3478 // SYN_STREAM not supported in SPDY>3
3481 SpdyFramer
framer(spdy_version_
);
3482 SpdySynStreamIR
syn_stream(1);
3483 syn_stream
.set_priority(1);
3484 syn_stream
.SetHeader("aa", "vv");
3485 syn_stream
.SetHeader("bb", "ww");
3486 SpdyHeaderBlock headers
= syn_stream
.name_value_block();
3487 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3488 EXPECT_TRUE(control_frame
.get() != NULL
);
3489 TestSpdyVisitor
visitor(spdy_version_
);
3490 visitor
.use_compression_
= true;
3491 visitor
.SimulateInFramer(
3492 reinterpret_cast<unsigned char*>(control_frame
->data()),
3493 control_frame
->size());
3494 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3495 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3498 TEST_P(SpdyFramerTest
, ReadCompressedSynReplyHeaderBlock
) {
3499 if (spdy_version_
> SPDY3
) {
3502 SpdyFramer
framer(spdy_version_
);
3503 SpdySynReplyIR
syn_reply(1);
3504 syn_reply
.SetHeader("alpha", "beta");
3505 syn_reply
.SetHeader("gamma", "delta");
3506 SpdyHeaderBlock headers
= syn_reply
.name_value_block();
3507 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynReply(syn_reply
));
3508 EXPECT_TRUE(control_frame
.get() != NULL
);
3509 TestSpdyVisitor
visitor(spdy_version_
);
3510 visitor
.use_compression_
= true;
3511 visitor
.SimulateInFramer(
3512 reinterpret_cast<unsigned char*>(control_frame
->data()),
3513 control_frame
->size());
3515 EXPECT_EQ(0, visitor
.syn_reply_frame_count_
);
3516 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3518 EXPECT_EQ(1, visitor
.syn_reply_frame_count_
);
3519 EXPECT_EQ(0, visitor
.headers_frame_count_
);
3521 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3524 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlock
) {
3525 SpdyFramer
framer(spdy_version_
);
3526 SpdyHeadersIR
headers_ir(1);
3527 headers_ir
.SetHeader("alpha", "beta");
3528 headers_ir
.SetHeader("gamma", "delta");
3529 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
3530 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
3531 EXPECT_TRUE(control_frame
.get() != NULL
);
3532 TestSpdyVisitor
visitor(spdy_version_
);
3533 visitor
.use_compression_
= true;
3534 visitor
.SimulateInFramer(
3535 reinterpret_cast<unsigned char*>(control_frame
->data()),
3536 control_frame
->size());
3537 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3538 // control_frame_header_data_count_ depends on the random sequence
3539 // produced by rand(), so adding, removing or running single tests
3540 // alters this value. The best we can do is assert that it happens
3542 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
3543 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3544 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3545 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3548 TEST_P(SpdyFramerTest
, ReadCompressedHeadersHeaderBlockWithHalfClose
) {
3549 SpdyFramer
framer(spdy_version_
);
3550 SpdyHeadersIR
headers_ir(1);
3551 headers_ir
.set_fin(true);
3552 headers_ir
.SetHeader("alpha", "beta");
3553 headers_ir
.SetHeader("gamma", "delta");
3554 SpdyHeaderBlock headers
= headers_ir
.name_value_block();
3555 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers_ir
));
3556 EXPECT_TRUE(control_frame
.get() != NULL
);
3557 TestSpdyVisitor
visitor(spdy_version_
);
3558 visitor
.use_compression_
= true;
3559 visitor
.SimulateInFramer(
3560 reinterpret_cast<unsigned char*>(control_frame
->data()),
3561 control_frame
->size());
3562 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3563 // control_frame_header_data_count_ depends on the random sequence
3564 // produced by rand(), so adding, removing or running single tests
3565 // alters this value. The best we can do is assert that it happens
3567 EXPECT_LE(2, visitor
.control_frame_header_data_count_
);
3568 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3569 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
3570 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
3573 TEST_P(SpdyFramerTest
, ControlFrameAtMaxSizeLimit
) {
3574 if (spdy_version_
> SPDY3
) {
3575 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3578 // First find the size of the header value in order to just reach the control
3580 SpdyFramer
framer(spdy_version_
);
3581 framer
.set_enable_compression(false);
3582 SpdySynStreamIR
syn_stream(1);
3583 syn_stream
.set_priority(1);
3584 syn_stream
.SetHeader("aa", "");
3585 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3586 const size_t kBigValueSize
=
3587 TestSpdyVisitor::sent_control_frame_max_size() - control_frame
->size();
3589 // Create a frame at exactly that size.
3590 string
big_value(kBigValueSize
, 'x');
3591 syn_stream
.SetHeader("aa", big_value
);
3592 control_frame
.reset(framer
.SerializeSynStream(syn_stream
));
3593 EXPECT_TRUE(control_frame
.get() != NULL
);
3594 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3595 control_frame
->size());
3597 TestSpdyVisitor
visitor(spdy_version_
);
3598 visitor
.SimulateInFramer(
3599 reinterpret_cast<unsigned char*>(control_frame
->data()),
3600 control_frame
->size());
3601 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3602 EXPECT_EQ(0, visitor
.error_count_
);
3603 EXPECT_EQ(1, visitor
.syn_frame_count_
);
3604 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3605 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3606 EXPECT_LT(kBigValueSize
, visitor
.header_buffer_length_
);
3609 // This test is disabled because Chromium is willing to accept control frames up
3610 // to the maximum size allowed by the specification, and SpdyFrameBuilder is not
3611 // capable of building larger frames.
3612 TEST_P(SpdyFramerTest
, DISABLED_ControlFrameTooLarge
) {
3613 if (spdy_version_
> SPDY3
) {
3614 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3617 // First find the size of the header value in order to just reach the control
3619 SpdyFramer
framer(spdy_version_
);
3620 framer
.set_enable_compression(false);
3621 SpdySynStreamIR
syn_stream(1);
3622 syn_stream
.SetHeader("aa", "");
3623 syn_stream
.set_priority(1);
3624 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3625 const size_t kBigValueSize
=
3626 SpdyConstants::GetFrameMaximumSize(spdy_version_
) -
3627 control_frame
->size() + 1;
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_
) + 1,
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_FALSE(visitor
.header_buffer_valid_
);
3646 EXPECT_EQ(1, visitor
.error_count_
);
3647 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
3648 visitor
.framer_
.error_code())
3649 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3650 EXPECT_EQ(0, visitor
.syn_frame_count_
);
3651 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3654 TEST_P(SpdyFramerTest
, TooLargeHeadersFrameUsesContinuation
) {
3655 if (spdy_version_
<= SPDY3
) {
3658 SpdyFramer
framer(spdy_version_
);
3659 framer
.set_enable_compression(false);
3660 SpdyHeadersIR
headers(1);
3661 headers
.set_padding_len(256);
3663 // Exact payload length will change with HPACK, but this should be long
3664 // enough to cause an overflow.
3665 const size_t kBigValueSize
= kControlFrameSizeLimit
;
3666 string
big_value(kBigValueSize
, 'x');
3667 headers
.SetHeader("aa", big_value
);
3668 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers
));
3669 EXPECT_TRUE(control_frame
.get() != NULL
);
3670 EXPECT_GT(control_frame
->size(),
3671 TestSpdyVisitor::sent_control_frame_max_size());
3673 TestSpdyVisitor
visitor(spdy_version_
);
3674 visitor
.SimulateInFramer(
3675 reinterpret_cast<unsigned char*>(control_frame
->data()),
3676 control_frame
->size());
3677 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3678 EXPECT_EQ(0, visitor
.error_count_
);
3679 EXPECT_EQ(1, visitor
.headers_frame_count_
);
3680 EXPECT_EQ(16, visitor
.continuation_count_
);
3681 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3684 TEST_P(SpdyFramerTest
, TooLargePushPromiseFrameUsesContinuation
) {
3685 if (spdy_version_
<= SPDY3
) {
3688 SpdyFramer
framer(spdy_version_
);
3689 framer
.set_enable_compression(false);
3690 SpdyPushPromiseIR
push_promise(1, 2);
3691 push_promise
.set_padding_len(256);
3693 // Exact payload length will change with HPACK, but this should be long
3694 // enough to cause an overflow.
3695 const size_t kBigValueSize
= kControlFrameSizeLimit
;
3696 string
big_value(kBigValueSize
, 'x');
3697 push_promise
.SetHeader("aa", big_value
);
3698 scoped_ptr
<SpdyFrame
> control_frame(
3699 framer
.SerializePushPromise(push_promise
));
3700 EXPECT_TRUE(control_frame
.get() != NULL
);
3701 EXPECT_GT(control_frame
->size(),
3702 TestSpdyVisitor::sent_control_frame_max_size());
3704 TestSpdyVisitor
visitor(spdy_version_
);
3705 visitor
.SimulateInFramer(
3706 reinterpret_cast<unsigned char*>(control_frame
->data()),
3707 control_frame
->size());
3708 EXPECT_TRUE(visitor
.header_buffer_valid_
);
3709 EXPECT_EQ(0, visitor
.error_count_
);
3710 EXPECT_EQ(1, visitor
.push_promise_frame_count_
);
3711 EXPECT_EQ(16, visitor
.continuation_count_
);
3712 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
3715 // Check that the framer stops delivering header data chunks once the visitor
3716 // declares it doesn't want any more. This is important to guard against
3717 // "zip bomb" types of attacks.
3718 TEST_P(SpdyFramerTest
, ControlFrameMuchTooLarge
) {
3719 const size_t kHeaderBufferChunks
= 4;
3720 const size_t kHeaderBufferSize
=
3721 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks
;
3722 const size_t kBigValueSize
= kHeaderBufferSize
* 2;
3723 string
big_value(kBigValueSize
, 'x');
3724 SpdyFramer
framer(spdy_version_
);
3725 SpdyHeadersIR
headers(1);
3726 headers
.set_priority(1);
3727 headers
.set_fin(true);
3728 headers
.SetHeader("aa", big_value
);
3729 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeHeaders(headers
));
3730 EXPECT_TRUE(control_frame
.get() != NULL
);
3731 TestSpdyVisitor
visitor(spdy_version_
);
3732 visitor
.set_header_buffer_size(kHeaderBufferSize
);
3733 visitor
.use_compression_
= true;
3734 visitor
.SimulateInFramer(
3735 reinterpret_cast<unsigned char*>(control_frame
->data()),
3736 control_frame
->size());
3737 EXPECT_FALSE(visitor
.header_buffer_valid_
);
3738 EXPECT_EQ(1, visitor
.error_count_
);
3739 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
,
3740 visitor
.framer_
.error_code())
3741 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3743 // The framer should have stoped delivering chunks after the visitor
3744 // signaled "stop" by returning false from OnControlFrameHeaderData().
3746 // control_frame_header_data_count_ depends on the random sequence
3747 // produced by rand(), so adding, removing or running single tests
3748 // alters this value. The best we can do is assert that it happens
3749 // at least kHeaderBufferChunks + 1.
3750 EXPECT_LE(kHeaderBufferChunks
+ 1,
3751 static_cast<unsigned>(visitor
.control_frame_header_data_count_
));
3752 EXPECT_EQ(0, visitor
.zero_length_control_frame_header_data_count_
);
3754 // The framer should not have sent half-close to the visitor.
3755 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
3758 TEST_P(SpdyFramerTest
, DecompressCorruptHeaderBlock
) {
3759 if (spdy_version_
> SPDY3
) {
3760 // Deflate compression doesn't apply to HPACK.
3763 SpdyFramer
framer(spdy_version_
);
3764 framer
.set_enable_compression(false);
3765 // Construct a SYN_STREAM control frame without compressing the header block,
3766 // and have the framer try to decompress it. This will cause the framer to
3767 // deal with a decompression error.
3768 SpdySynStreamIR
syn_stream(1);
3769 syn_stream
.set_priority(1);
3770 syn_stream
.SetHeader("aa", "alpha beta gamma delta");
3771 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSynStream(syn_stream
));
3772 TestSpdyVisitor
visitor(spdy_version_
);
3773 visitor
.use_compression_
= true;
3774 visitor
.SimulateInFramer(
3775 reinterpret_cast<unsigned char*>(control_frame
->data()),
3776 control_frame
->size());
3777 EXPECT_EQ(1, visitor
.error_count_
);
3778 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE
, visitor
.framer_
.error_code())
3779 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3780 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
3783 TEST_P(SpdyFramerTest
, ControlFrameSizesAreValidated
) {
3784 SpdyFramer
framer(spdy_version_
);
3785 // Create a GoAway frame that has a few extra bytes at the end.
3786 // We create enough overhead to overflow the framer's control frame buffer.
3787 ASSERT_LE(SpdyFramer::kControlFrameBufferSize
, 250u);
3788 const size_t length
= SpdyFramer::kControlFrameBufferSize
+ 1;
3789 const unsigned char kV3FrameData
[] = { // Also applies for V2.
3790 0x80, spdy_version_ch_
, 0x00, 0x07,
3791 0x00, 0x00, 0x00, static_cast<unsigned char>(length
),
3792 0x00, 0x00, 0x00, 0x00, // Stream ID
3793 0x00, 0x00, 0x00, 0x00, // Status
3796 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3797 // since it may carry opaque data. Verify that minimal length is tested.
3798 ASSERT_GT(framer
.GetGoAwayMinimumSize(), framer
.GetControlFrameHeaderSize());
3799 const size_t less_than_min_length
=
3800 framer
.GetGoAwayMinimumSize() - framer
.GetControlFrameHeaderSize() - 1;
3801 ASSERT_LE(less_than_min_length
, std::numeric_limits
<unsigned char>::max());
3802 const unsigned char kV4FrameData
[] = {
3803 0x00, 0x00, static_cast<unsigned char>(less_than_min_length
), 0x07,
3804 0x00, 0x00, 0x00, 0x00,
3805 0x00, 0x00, 0x00, 0x00, // Stream Id
3806 0x00, 0x00, 0x00, 0x00, // Status
3809 const size_t pad_length
=
3810 length
+ framer
.GetControlFrameHeaderSize() -
3811 (IsSpdy4() ? sizeof(kV4FrameData
) : sizeof(kV3FrameData
));
3812 string
pad(pad_length
, 'A');
3813 TestSpdyVisitor
visitor(spdy_version_
);
3816 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3818 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3820 visitor
.SimulateInFramer(
3821 reinterpret_cast<const unsigned char*>(pad
.c_str()),
3824 EXPECT_EQ(1, visitor
.error_count_
); // This generated an error.
3825 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
3826 visitor
.framer_
.error_code())
3827 << SpdyFramer::ErrorCodeToString(framer
.error_code());
3828 EXPECT_EQ(0, visitor
.goaway_count_
); // Frame not parsed.
3831 TEST_P(SpdyFramerTest
, ReadZeroLenSettingsFrame
) {
3832 SpdyFramer
framer(spdy_version_
);
3833 SpdySettingsIR settings_ir
;
3834 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3835 SetFrameLength(control_frame
.get(), 0, spdy_version_
);
3836 TestSpdyVisitor
visitor(spdy_version_
);
3837 visitor
.use_compression_
= false;
3838 visitor
.SimulateInFramer(
3839 reinterpret_cast<unsigned char*>(control_frame
->data()),
3840 framer
.GetControlFrameHeaderSize());
3841 if (spdy_version_
<= SPDY3
) {
3842 // Should generate an error, since zero-len settings frames are unsupported.
3843 EXPECT_EQ(1, visitor
.error_count_
);
3845 // Zero-len settings frames are permitted as of SPDY 4.
3846 EXPECT_EQ(0, visitor
.error_count_
);
3850 // Tests handling of SETTINGS frames with invalid length.
3851 TEST_P(SpdyFramerTest
, ReadBogusLenSettingsFrame
) {
3852 SpdyFramer
framer(spdy_version_
);
3853 SpdySettingsIR settings_ir
;
3855 // Add a setting to pad the frame so that we don't get a buffer overflow when
3856 // calling SimulateInFramer() below.
3857 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
,
3861 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3862 const size_t kNewLength
= 14;
3863 SetFrameLength(control_frame
.get(), kNewLength
, spdy_version_
);
3864 TestSpdyVisitor
visitor(spdy_version_
);
3865 visitor
.use_compression_
= false;
3866 visitor
.SimulateInFramer(
3867 reinterpret_cast<unsigned char*>(control_frame
->data()),
3868 framer
.GetControlFrameHeaderSize() + kNewLength
);
3869 // Should generate an error, since its not possible to have a
3870 // settings frame of length kNewLength.
3871 EXPECT_EQ(1, visitor
.error_count_
);
3874 // Tests handling of SETTINGS frames larger than the frame buffer size.
3875 TEST_P(SpdyFramerTest
, ReadLargeSettingsFrame
) {
3876 SpdyFramer
framer(spdy_version_
);
3877 SpdySettingsIR settings_ir
;
3878 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
3882 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 2),
3886 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 3),
3891 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
3892 EXPECT_LT(SpdyFramer::kControlFrameBufferSize
,
3893 control_frame
->size());
3894 TestSpdyVisitor
visitor(spdy_version_
);
3895 visitor
.use_compression_
= false;
3897 // Read all at once.
3898 visitor
.SimulateInFramer(
3899 reinterpret_cast<unsigned char*>(control_frame
->data()),
3900 control_frame
->size());
3901 EXPECT_EQ(0, visitor
.error_count_
);
3902 EXPECT_EQ(3, visitor
.setting_count_
);
3903 if (spdy_version_
> SPDY3
) {
3904 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3907 // Read data in small chunks.
3908 size_t framed_data
= 0;
3909 size_t unframed_data
= control_frame
->size();
3910 size_t kReadChunkSize
= 5; // Read five bytes at a time.
3911 while (unframed_data
> 0) {
3912 size_t to_read
= std::min(kReadChunkSize
, unframed_data
);
3913 visitor
.SimulateInFramer(
3914 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
3916 unframed_data
-= to_read
;
3917 framed_data
+= to_read
;
3919 EXPECT_EQ(0, visitor
.error_count_
);
3920 EXPECT_EQ(3 * 2, visitor
.setting_count_
);
3921 if (spdy_version_
> SPDY3
) {
3922 EXPECT_EQ(2, visitor
.settings_ack_sent_
);
3926 // Tests handling of SETTINGS frame with duplicate entries.
3927 TEST_P(SpdyFramerTest
, ReadDuplicateSettings
) {
3928 SpdyFramer
framer(spdy_version_
);
3930 const unsigned char kV2FrameData
[] = {
3931 0x80, spdy_version_ch_
, 0x00, 0x04,
3932 0x00, 0x00, 0x00, 0x1C,
3933 0x00, 0x00, 0x00, 0x03,
3934 0x01, 0x00, 0x00, 0x00, // 1st Setting
3935 0x00, 0x00, 0x00, 0x02,
3936 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3937 0x00, 0x00, 0x00, 0x03,
3938 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3939 0x00, 0x00, 0x00, 0x03,
3941 const unsigned char kV3FrameData
[] = {
3942 0x80, spdy_version_ch_
, 0x00, 0x04,
3943 0x00, 0x00, 0x00, 0x1C,
3944 0x00, 0x00, 0x00, 0x03,
3945 0x00, 0x00, 0x00, 0x01, // 1st Setting
3946 0x00, 0x00, 0x00, 0x02,
3947 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3948 0x00, 0x00, 0x00, 0x03,
3949 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3950 0x00, 0x00, 0x00, 0x03,
3952 const unsigned char kV4FrameData
[] = {
3953 0x00, 0x00, 0x12, 0x04,
3954 0x00, 0x00, 0x00, 0x00,
3955 0x00, 0x00, 0x01, // 1st Setting
3956 0x00, 0x00, 0x00, 0x02,
3957 0x00, 0x01, // 2nd (duplicate) Setting
3958 0x00, 0x00, 0x00, 0x03,
3959 0x00, 0x03, // 3rd (unprocessed) Setting
3960 0x00, 0x00, 0x00, 0x03,
3963 TestSpdyVisitor
visitor(spdy_version_
);
3964 visitor
.use_compression_
= false;
3966 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
3967 } else if (IsSpdy3()) {
3968 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
3970 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
3974 EXPECT_EQ(1, visitor
.setting_count_
);
3975 EXPECT_EQ(1, visitor
.error_count_
);
3977 // In SPDY 4+, duplicate settings are allowed;
3978 // each setting replaces the previous value for that setting.
3979 EXPECT_EQ(3, visitor
.setting_count_
);
3980 EXPECT_EQ(0, visitor
.error_count_
);
3981 EXPECT_EQ(1, visitor
.settings_ack_sent_
);
3985 // Tests handling of SETTINGS frame with a setting we don't recognize.
3986 TEST_P(SpdyFramerTest
, ReadUnknownSettingsId
) {
3987 SpdyFramer
framer(spdy_version_
);
3989 const unsigned char kV2FrameData
[] = {
3990 0x80, spdy_version_ch_
, 0x00, 0x04,
3991 0x00, 0x00, 0x00, 0x1C,
3992 0x00, 0x00, 0x00, 0x01,
3993 0x10, 0x00, 0x00, 0x00, // 1st Setting
3994 0x00, 0x00, 0x00, 0x02,
3996 const unsigned char kV3FrameData
[] = {
3997 0x80, spdy_version_ch_
, 0x00, 0x04,
3998 0x00, 0x00, 0x00, 0x1C,
3999 0x00, 0x00, 0x00, 0x01,
4000 0x00, 0x00, 0x00, 0x10, // 1st Setting
4001 0x00, 0x00, 0x00, 0x02,
4003 const unsigned char kV4FrameData
[] = {
4004 0x00, 0x00, 0x06, 0x04,
4005 0x00, 0x00, 0x00, 0x00,
4006 0x00, 0x00, 0x10, // 1st Setting
4007 0x00, 0x00, 0x00, 0x02,
4010 TestSpdyVisitor
visitor(spdy_version_
);
4011 visitor
.use_compression_
= false;
4013 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
4014 } else if (IsSpdy3()) {
4015 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
4017 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
4021 EXPECT_EQ(0, visitor
.setting_count_
);
4022 EXPECT_EQ(1, visitor
.error_count_
);
4024 // In SPDY 4+, we ignore unknown settings because of extensions.
4025 EXPECT_EQ(0, visitor
.setting_count_
);
4026 EXPECT_EQ(0, visitor
.error_count_
);
4030 // Tests handling of SETTINGS frame with entries out of order.
4031 TEST_P(SpdyFramerTest
, ReadOutOfOrderSettings
) {
4032 SpdyFramer
framer(spdy_version_
);
4034 const unsigned char kV2FrameData
[] = {
4035 0x80, spdy_version_ch_
, 0x00, 0x04,
4036 0x00, 0x00, 0x00, 0x1C,
4037 0x00, 0x00, 0x00, 0x03,
4038 0x02, 0x00, 0x00, 0x00, // 1st Setting
4039 0x00, 0x00, 0x00, 0x02,
4040 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4041 0x00, 0x00, 0x00, 0x03,
4042 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4043 0x00, 0x00, 0x00, 0x03,
4045 const unsigned char kV3FrameData
[] = {
4046 0x80, spdy_version_ch_
, 0x00, 0x04,
4047 0x00, 0x00, 0x00, 0x1C,
4048 0x00, 0x00, 0x00, 0x03,
4049 0x00, 0x00, 0x00, 0x02, // 1st Setting
4050 0x00, 0x00, 0x00, 0x02,
4051 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4052 0x00, 0x00, 0x00, 0x03,
4053 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4054 0x00, 0x00, 0x00, 0x03,
4056 const unsigned char kV4FrameData
[] = {
4057 0x00, 0x00, 0x12, 0x04,
4058 0x00, 0x00, 0x00, 0x00,
4059 0x00, 0x00, 0x02, // 1st Setting
4060 0x00, 0x00, 0x00, 0x02,
4061 0x00, 0x01, // 2nd (out of order) Setting
4062 0x00, 0x00, 0x00, 0x03,
4063 0x00, 0x03, // 3rd (unprocessed) Setting
4064 0x00, 0x00, 0x00, 0x03,
4067 TestSpdyVisitor
visitor(spdy_version_
);
4068 visitor
.use_compression_
= false;
4070 visitor
.SimulateInFramer(kV2FrameData
, sizeof(kV2FrameData
));
4071 } else if (IsSpdy3()) {
4072 visitor
.SimulateInFramer(kV3FrameData
, sizeof(kV3FrameData
));
4074 visitor
.SimulateInFramer(kV4FrameData
, sizeof(kV4FrameData
));
4078 EXPECT_EQ(1, visitor
.setting_count_
);
4079 EXPECT_EQ(1, visitor
.error_count_
);
4081 // In SPDY 4+, settings are allowed in any order.
4082 EXPECT_EQ(3, visitor
.setting_count_
);
4083 EXPECT_EQ(0, visitor
.error_count_
);
4087 TEST_P(SpdyFramerTest
, ProcessSettingsAckFrame
) {
4088 if (spdy_version_
<= SPDY3
) {
4091 SpdyFramer
framer(spdy_version_
);
4093 const unsigned char kFrameData
[] = {
4094 0x00, 0x00, 0x00, 0x04, 0x01,
4095 0x00, 0x00, 0x00, 0x00,
4098 TestSpdyVisitor
visitor(spdy_version_
);
4099 visitor
.use_compression_
= false;
4100 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
4102 EXPECT_EQ(0, visitor
.error_count_
);
4103 EXPECT_EQ(0, visitor
.setting_count_
);
4104 EXPECT_EQ(1, visitor
.settings_ack_received_
);
4107 TEST_P(SpdyFramerTest
, ProcessDataFrameWithPadding
) {
4108 if (spdy_version_
<= SPDY3
) {
4112 const int kPaddingLen
= 119;
4113 const char data_payload
[] = "hello";
4115 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4116 SpdyFramer
framer(spdy_version_
);
4117 framer
.set_visitor(&visitor
);
4119 SpdyDataIR
data_ir(1, StringPiece(data_payload
, strlen(data_payload
)));
4120 data_ir
.set_padding_len(kPaddingLen
);
4121 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4122 ASSERT_TRUE(frame
.get() != NULL
);
4124 int bytes_consumed
= 0;
4126 // Send the frame header.
4127 EXPECT_CALL(visitor
, OnDataFrameHeader(1,
4128 kPaddingLen
+ strlen(data_payload
),
4130 CHECK_EQ(framer
.GetDataFrameMinimumSize(),
4131 framer
.ProcessInput(frame
->data(),
4132 framer
.GetDataFrameMinimumSize()));
4133 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH
);
4134 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4135 bytes_consumed
+= framer
.GetDataFrameMinimumSize();
4137 // Send the padding length field.
4138 EXPECT_CALL(visitor
, OnStreamPadding(1, 1));
4139 CHECK_EQ(1u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 1));
4140 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME
);
4141 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4142 bytes_consumed
+= 1;
4144 // Send the first two bytes of the data payload, i.e., "he".
4145 EXPECT_CALL(visitor
, OnStreamFrameData(1, _
, 2, false));
4146 CHECK_EQ(2u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 2));
4147 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME
);
4148 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4149 bytes_consumed
+= 2;
4151 // Send the rest three bytes of the data payload, i.e., "llo".
4152 EXPECT_CALL(visitor
, OnStreamFrameData(1, _
, 3, false));
4153 CHECK_EQ(3u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 3));
4154 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_CONSUME_PADDING
);
4155 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4156 bytes_consumed
+= 3;
4158 // Send the first 100 bytes of the padding payload.
4159 EXPECT_CALL(visitor
, OnStreamPadding(1, 100));
4160 CHECK_EQ(100u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 100));
4161 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_CONSUME_PADDING
);
4162 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4163 bytes_consumed
+= 100;
4165 // Send rest of the padding payload.
4166 EXPECT_CALL(visitor
, OnStreamPadding(1, 18));
4167 CHECK_EQ(18u, framer
.ProcessInput(frame
->data() + bytes_consumed
, 18));
4168 CHECK_EQ(framer
.state(), SpdyFramer::SPDY_RESET
);
4169 CHECK_EQ(framer
.error_code(), SpdyFramer::SPDY_NO_ERROR
);
4172 TEST_P(SpdyFramerTest
, ReadWindowUpdate
) {
4173 SpdyFramer
framer(spdy_version_
);
4174 scoped_ptr
<SpdyFrame
> control_frame(
4175 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4176 TestSpdyVisitor
visitor(spdy_version_
);
4177 visitor
.SimulateInFramer(
4178 reinterpret_cast<unsigned char*>(control_frame
->data()),
4179 control_frame
->size());
4180 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
4181 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
4184 TEST_P(SpdyFramerTest
, ReceiveCredentialFrame
) {
4188 SpdyFramer
framer(spdy_version_
);
4189 const unsigned char kV3FrameData
[] = { // Also applies for V2.
4190 0x80, spdy_version_ch_
, 0x00, 0x0A,
4191 0x00, 0x00, 0x00, 0x33,
4192 0x00, 0x03, 0x00, 0x00,
4193 0x00, 0x05, 'p', 'r',
4194 'o', 'o', 'f', 0x00,
4195 0x00, 0x00, 0x06, 'a',
4197 't', 0x00, 0x00, 0x00,
4198 0x0C, 'a', 'n', 'o',
4201 't', 0x00, 0x00, 0x00,
4202 0x0A, 'f', 'i', 'n',
4206 TestSpdyVisitor
visitor(spdy_version_
);
4207 visitor
.use_compression_
= false;
4208 visitor
.SimulateInFramer(kV3FrameData
, arraysize(kV3FrameData
));
4209 EXPECT_EQ(0, visitor
.error_count_
);
4212 TEST_P(SpdyFramerTest
, ReadCredentialFrameFollowedByAnotherFrame
) {
4216 SpdyFramer
framer(spdy_version_
);
4217 const unsigned char kV3FrameData
[] = { // Also applies for V2.
4218 0x80, spdy_version_ch_
, 0x00, 0x0A,
4219 0x00, 0x00, 0x00, 0x33,
4220 0x00, 0x03, 0x00, 0x00,
4221 0x00, 0x05, 'p', 'r',
4222 'o', 'o', 'f', 0x00,
4223 0x00, 0x00, 0x06, 'a',
4225 't', 0x00, 0x00, 0x00,
4226 0x0C, 'a', 'n', 'o',
4229 't', 0x00, 0x00, 0x00,
4230 0x0A, 'f', 'i', 'n',
4234 TestSpdyVisitor
visitor(spdy_version_
);
4235 visitor
.use_compression_
= false;
4236 string
multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData
),
4237 arraysize(kV3FrameData
));
4238 scoped_ptr
<SpdyFrame
> control_frame(
4239 framer
.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4240 multiple_frame_data
.append(string(control_frame
->data(),
4241 control_frame
->size()));
4242 visitor
.SimulateInFramer(
4243 reinterpret_cast<unsigned const char*>(multiple_frame_data
.data()),
4244 multiple_frame_data
.length());
4245 EXPECT_EQ(0, visitor
.error_count_
);
4246 EXPECT_EQ(1u, visitor
.last_window_update_stream_
);
4247 EXPECT_EQ(2u, visitor
.last_window_update_delta_
);
4250 TEST_P(SpdyFramerTest
, ReadCompressedPushPromise
) {
4251 if (spdy_version_
<= SPDY3
) {
4255 SpdyFramer
framer(spdy_version_
);
4256 SpdyPushPromiseIR
push_promise(42, 57);
4257 push_promise
.SetHeader("foo", "bar");
4258 push_promise
.SetHeader("bar", "foofoo");
4259 SpdyHeaderBlock headers
= push_promise
.name_value_block();
4260 scoped_ptr
<SpdySerializedFrame
> frame(
4261 framer
.SerializePushPromise(push_promise
));
4262 EXPECT_TRUE(frame
.get() != NULL
);
4263 TestSpdyVisitor
visitor(spdy_version_
);
4264 visitor
.use_compression_
= true;
4265 visitor
.SimulateInFramer(
4266 reinterpret_cast<unsigned char*>(frame
->data()),
4268 EXPECT_EQ(42u, visitor
.last_push_promise_stream_
);
4269 EXPECT_EQ(57u, visitor
.last_push_promise_promised_stream_
);
4270 EXPECT_TRUE(CompareHeaderBlocks(&headers
, &visitor
.headers_
));
4273 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuation
) {
4274 if (spdy_version_
<= SPDY3
) {
4278 const unsigned char kInput
[] = {
4279 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4280 0x00, 0x00, 0x00, 0x01, // Stream 1
4281 0x03, // Padding of 3.
4282 0x00, 0x06, 0x63, 0x6f,
4283 0x6f, 0x6b, 0x69, 0x65,
4284 0x07, 0x66, 0x6f, 0x6f,
4285 0x3d, 0x62, 0x61, 0x72,
4288 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4289 0x00, 0x00, 0x00, 0x01, // Stream 1
4290 0x00, 0x06, 0x63, 0x6f,
4291 0x6f, 0x6b, 0x69, 0x65,
4292 0x08, 0x62, 0x61, 0x7a,
4293 0x3d, 0x62, 0x69, 0x6e,
4294 0x67, 0x00, 0x06, 0x63,
4296 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4297 0x00, 0x00, 0x00, 0x01, // Stream 1
4298 0x6f, 0x6f, 0x6b, 0x69,
4299 0x65, 0x00, 0x00, 0x04,
4300 0x6e, 0x61, 0x6d, 0x65,
4301 0x05, 0x76, 0x61, 0x6c,
4305 TestSpdyVisitor
visitor(spdy_version_
);
4306 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4308 EXPECT_EQ(0, visitor
.error_count_
);
4309 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4310 EXPECT_EQ(2, visitor
.continuation_count_
);
4311 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4312 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
4314 EXPECT_THAT(visitor
.headers_
,
4315 testing::ElementsAre(
4316 testing::Pair("cookie", "foo=bar; baz=bing; "),
4317 testing::Pair("name", "value")));
4320 TEST_P(SpdyFramerTest
, ReadHeadersWithContinuationAndFin
) {
4321 if (spdy_version_
<= SPDY3
) {
4325 const unsigned char kInput
[] = {
4326 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4327 0x00, 0x00, 0x00, 0x01, // Stream 1
4328 0x00, 0x06, 0x63, 0x6f,
4329 0x6f, 0x6b, 0x69, 0x65,
4330 0x07, 0x66, 0x6f, 0x6f,
4331 0x3d, 0x62, 0x61, 0x72,
4333 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4334 0x00, 0x00, 0x00, 0x01, // Stream 1
4335 0x00, 0x06, 0x63, 0x6f,
4336 0x6f, 0x6b, 0x69, 0x65,
4337 0x08, 0x62, 0x61, 0x7a,
4338 0x3d, 0x62, 0x69, 0x6e,
4339 0x67, 0x00, 0x06, 0x63,
4341 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4342 0x00, 0x00, 0x00, 0x01, // Stream 1
4343 0x6f, 0x6f, 0x6b, 0x69,
4344 0x65, 0x00, 0x00, 0x04,
4345 0x6e, 0x61, 0x6d, 0x65,
4346 0x05, 0x76, 0x61, 0x6c,
4350 SpdyFramer
framer(spdy_version_
);
4351 TestSpdyVisitor
visitor(spdy_version_
);
4352 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4354 EXPECT_EQ(0, visitor
.error_count_
);
4355 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4356 EXPECT_EQ(2, visitor
.continuation_count_
);
4357 EXPECT_EQ(1, visitor
.fin_flag_count_
);
4358 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4359 EXPECT_EQ(1, visitor
.zero_length_data_frame_count_
);
4361 EXPECT_THAT(visitor
.headers_
,
4362 testing::ElementsAre(
4363 testing::Pair("cookie", "foo=bar; baz=bing; "),
4364 testing::Pair("name", "value")));
4367 TEST_P(SpdyFramerTest
, ReadPushPromiseWithContinuation
) {
4368 if (spdy_version_
<= SPDY3
) {
4372 const unsigned char kInput
[] = {
4373 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4374 0x08, 0x00, 0x00, 0x00, // PADDED
4375 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4376 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4377 0x63, 0x6f, 0x6f, 0x6b,
4378 0x69, 0x65, 0x07, 0x66,
4379 0x6f, 0x6f, 0x3d, 0x62,
4380 0x61, 0x72, 0x00, 0x00,
4382 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4383 0x00, 0x00, 0x00, 0x00,
4384 0x01, 0x00, 0x06, 0x63, // Stream 1
4385 0x6f, 0x6f, 0x6b, 0x69,
4386 0x65, 0x08, 0x62, 0x61,
4387 0x7a, 0x3d, 0x62, 0x69,
4388 0x6e, 0x67, 0x00, 0x06,
4391 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4392 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4393 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4394 0x69, 0x65, 0x00, 0x00,
4395 0x04, 0x6e, 0x61, 0x6d,
4396 0x65, 0x05, 0x76, 0x61,
4400 SpdyFramer
framer(spdy_version_
);
4401 TestSpdyVisitor
visitor(spdy_version_
);
4402 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4404 EXPECT_EQ(0, visitor
.error_count_
);
4405 EXPECT_EQ(1u, visitor
.last_push_promise_stream_
);
4406 EXPECT_EQ(42u, visitor
.last_push_promise_promised_stream_
);
4407 EXPECT_EQ(2, visitor
.continuation_count_
);
4408 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4409 EXPECT_EQ(0, visitor
.zero_length_data_frame_count_
);
4411 EXPECT_THAT(visitor
.headers_
,
4412 testing::ElementsAre(
4413 testing::Pair("cookie", "foo=bar; baz=bing; "),
4414 testing::Pair("name", "value")));
4417 TEST_P(SpdyFramerTest
, ReadContinuationWithWrongStreamId
) {
4418 if (spdy_version_
<= SPDY3
) {
4422 const unsigned char kInput
[] = {
4423 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4424 0x00, 0x00, 0x00, 0x01, // Stream 1
4425 0x00, 0x06, 0x63, 0x6f,
4426 0x6f, 0x6b, 0x69, 0x65,
4427 0x07, 0x66, 0x6f, 0x6f,
4428 0x3d, 0x62, 0x61, 0x72,
4430 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4431 0x00, 0x00, 0x00, 0x02, // Stream 2
4432 0x00, 0x06, 0x63, 0x6f,
4433 0x6f, 0x6b, 0x69, 0x65,
4434 0x08, 0x62, 0x61, 0x7a,
4435 0x3d, 0x62, 0x69, 0x6e,
4436 0x67, 0x00, 0x06, 0x63,
4439 SpdyFramer
framer(spdy_version_
);
4440 TestSpdyVisitor
visitor(spdy_version_
);
4441 framer
.set_visitor(&visitor
);
4442 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4444 EXPECT_EQ(1, visitor
.error_count_
);
4445 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
4446 visitor
.framer_
.error_code())
4447 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4448 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4449 EXPECT_EQ(0, visitor
.continuation_count_
);
4450 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4453 TEST_P(SpdyFramerTest
, ReadContinuationOutOfOrder
) {
4454 if (spdy_version_
<= SPDY3
) {
4458 const unsigned char kInput
[] = {
4459 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4460 0x00, 0x00, 0x00, 0x01, // Stream 1
4461 0x00, 0x06, 0x63, 0x6f,
4462 0x6f, 0x6b, 0x69, 0x65,
4463 0x07, 0x66, 0x6f, 0x6f,
4464 0x3d, 0x62, 0x61, 0x72,
4467 SpdyFramer
framer(spdy_version_
);
4468 TestSpdyVisitor
visitor(spdy_version_
);
4469 framer
.set_visitor(&visitor
);
4470 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4472 EXPECT_EQ(1, visitor
.error_count_
);
4473 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4474 visitor
.framer_
.error_code())
4475 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4476 EXPECT_EQ(0, visitor
.continuation_count_
);
4477 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4480 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveData
) {
4481 if (spdy_version_
<= SPDY3
) {
4485 const unsigned char kInput
[] = {
4486 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4487 0x00, 0x00, 0x00, 0x01, // Stream 1
4488 0x00, 0x06, 0x63, 0x6f,
4489 0x6f, 0x6b, 0x69, 0x65,
4490 0x07, 0x66, 0x6f, 0x6f,
4491 0x3d, 0x62, 0x61, 0x72,
4493 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4494 0x00, 0x00, 0x00, 0x04,
4495 0xde, 0xad, 0xbe, 0xef,
4498 SpdyFramer
framer(spdy_version_
);
4499 TestSpdyVisitor
visitor(spdy_version_
);
4500 framer
.set_visitor(&visitor
);
4501 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4503 EXPECT_EQ(1, visitor
.error_count_
);
4504 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4505 visitor
.framer_
.error_code())
4506 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4507 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4508 EXPECT_EQ(0, visitor
.continuation_count_
);
4509 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4510 EXPECT_EQ(0, visitor
.data_frame_count_
);
4513 TEST_P(SpdyFramerTest
, ExpectContinuationReceiveControlFrame
) {
4514 if (spdy_version_
<= SPDY3
) {
4518 const unsigned char kInput
[] = {
4519 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4520 0x00, 0x00, 0x00, 0x01, // Stream 1
4521 0x00, 0x06, 0x63, 0x6f,
4522 0x6f, 0x6b, 0x69, 0x65,
4523 0x07, 0x66, 0x6f, 0x6f,
4524 0x3d, 0x62, 0x61, 0x72,
4526 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4527 0x00, 0x00, 0x00, 0x01, // Stream 1
4528 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4529 0x6f, 0x6b, 0x69, 0x65,
4530 0x08, 0x62, 0x61, 0x7a,
4531 0x3d, 0x62, 0x69, 0x6e,
4532 0x67, 0x00, 0x06, 0x63,
4535 SpdyFramer
framer(spdy_version_
);
4536 TestSpdyVisitor
visitor(spdy_version_
);
4537 framer
.set_visitor(&visitor
);
4538 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4540 EXPECT_EQ(1, visitor
.error_count_
);
4541 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME
,
4542 visitor
.framer_
.error_code())
4543 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4544 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4545 EXPECT_EQ(0, visitor
.continuation_count_
);
4546 EXPECT_EQ(0u, visitor
.header_buffer_length_
);
4547 EXPECT_EQ(0, visitor
.data_frame_count_
);
4550 TEST_P(SpdyFramerTest
, EndSegmentOnDataFrame
) {
4551 if (spdy_version_
<= SPDY3
) {
4554 const unsigned char kInput
[] = {
4555 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4556 0x00, 0x00, 0x00, 0x01, // Stream 1
4557 0xde, 0xad, 0xbe, 0xef,
4558 0xde, 0xad, 0xbe, 0xef,
4559 0xde, 0xad, 0xbe, 0xef,
4562 TestSpdyVisitor
visitor(spdy_version_
);
4563 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4565 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4566 EXPECT_EQ(0, visitor
.error_count_
);
4567 EXPECT_EQ(12, visitor
.data_bytes_
);
4568 EXPECT_EQ(0, visitor
.fin_frame_count_
);
4569 EXPECT_EQ(0, visitor
.fin_flag_count_
);
4572 TEST_P(SpdyFramerTest
, EndSegmentOnHeadersFrame
) {
4573 if (spdy_version_
<= SPDY3
) {
4576 const unsigned char kInput
[] = {
4577 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4578 0x00, 0x00, 0x00, 0x01, // Stream 1
4579 0x00, 0x06, 0x63, 0x6f,
4580 0x6f, 0x6b, 0x69, 0x65,
4581 0x07, 0x66, 0x6f, 0x6f,
4582 0x3d, 0x62, 0x61, 0x72,
4585 TestSpdyVisitor
visitor(spdy_version_
);
4586 visitor
.SimulateInFramer(kInput
, sizeof(kInput
));
4588 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4589 EXPECT_EQ(0, visitor
.error_count_
);
4590 EXPECT_EQ(1, visitor
.headers_frame_count_
);
4591 EXPECT_EQ(1, visitor
.zero_length_control_frame_header_data_count_
);
4593 EXPECT_THAT(visitor
.headers_
,
4594 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4597 TEST_P(SpdyFramerTest
, ReadGarbage
) {
4598 SpdyFramer
framer(spdy_version_
);
4599 unsigned char garbage_frame
[256];
4600 memset(garbage_frame
, ~0, sizeof(garbage_frame
));
4601 TestSpdyVisitor
visitor(spdy_version_
);
4602 visitor
.use_compression_
= false;
4603 visitor
.SimulateInFramer(garbage_frame
, sizeof(garbage_frame
));
4604 EXPECT_EQ(1, visitor
.error_count_
);
4607 TEST_P(SpdyFramerTest
, ReadUnknownExtensionFrame
) {
4608 if (spdy_version_
<= SPDY3
) {
4611 SpdyFramer
framer(spdy_version_
);
4613 // The unrecognized frame type should still have a valid length.
4614 const unsigned char unknown_frame
[] = {
4615 0x00, 0x00, 0x08, 0xff, 0xff,
4616 0xff, 0xff, 0xff, 0xff,
4617 0xff, 0xff, 0xff, 0xff,
4618 0xff, 0xff, 0xff, 0xff,
4620 TestSpdyVisitor
visitor(spdy_version_
);
4622 // Simulate the case where the stream id validation checks out.
4623 visitor
.on_unknown_frame_result_
= true;
4624 visitor
.use_compression_
= false;
4625 visitor
.SimulateInFramer(unknown_frame
, arraysize(unknown_frame
));
4626 EXPECT_EQ(0, visitor
.error_count_
);
4628 // Follow it up with a valid control frame to make sure we handle
4629 // subsequent frames correctly.
4630 SpdySettingsIR settings_ir
;
4631 settings_ir
.AddSetting(SpdyConstants::ParseSettingId(spdy_version_
, 1),
4635 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeSettings(settings_ir
));
4636 visitor
.SimulateInFramer(
4637 reinterpret_cast<unsigned char*>(control_frame
->data()),
4638 control_frame
->size());
4639 EXPECT_EQ(0, visitor
.error_count_
);
4640 EXPECT_EQ(1u, static_cast<unsigned>(visitor
.setting_count_
));
4641 EXPECT_EQ(1u, static_cast<unsigned>(visitor
.settings_ack_sent_
));
4644 TEST_P(SpdyFramerTest
, ReadGarbageWithValidLength
) {
4648 SpdyFramer
framer(spdy_version_
);
4649 const unsigned char kFrameData
[] = {
4650 0x00, 0x00, 0x08, 0xff, 0xff,
4651 0xff, 0xff, 0xff, 0xff,
4652 0xff, 0xff, 0xff, 0xff,
4653 0xff, 0xff, 0xff, 0xff,
4655 TestSpdyVisitor
visitor(spdy_version_
);
4656 visitor
.use_compression_
= false;
4657 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
4658 EXPECT_EQ(1, visitor
.error_count_
);
4661 TEST_P(SpdyFramerTest
, ReadGarbageWithValidVersion
) {
4663 // Not valid for SPDY 4 since there is no version field.
4666 SpdyFramer
framer(spdy_version_
);
4667 const unsigned char kFrameData
[] = {
4668 0x80, spdy_version_ch_
, 0xff, 0xff,
4669 0xff, 0xff, 0xff, 0xff,
4671 TestSpdyVisitor
visitor(spdy_version_
);
4672 visitor
.use_compression_
= false;
4673 visitor
.SimulateInFramer(kFrameData
, arraysize(kFrameData
));
4674 EXPECT_EQ(1, visitor
.error_count_
);
4677 TEST_P(SpdyFramerTest
, ReadGarbageHPACKEncoding
) {
4678 if (spdy_version_
<= SPDY3
) {
4681 const unsigned char kInput
[] = {
4682 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4683 0x00, 0x00, 0x00, 0x01, // Stream 1
4684 0xef, 0xef, 0xff, 0xff,
4685 0xff, 0xff, 0xff, 0xff,
4686 0xff, 0xff, 0xff, 0xff,
4687 0xff, 0xff, 0xff, 0xff,
4691 TestSpdyVisitor
visitor(spdy_version_
);
4692 visitor
.SimulateInFramer(kInput
, arraysize(kInput
));
4693 EXPECT_EQ(1, visitor
.error_count_
);
4696 TEST_P(SpdyFramerTest
, SizesTest
) {
4697 SpdyFramer
framer(spdy_version_
);
4699 EXPECT_EQ(9u, framer
.GetDataFrameMinimumSize());
4700 EXPECT_EQ(9u, framer
.GetControlFrameHeaderSize());
4701 EXPECT_EQ(14u, framer
.GetSynStreamMinimumSize());
4702 EXPECT_EQ(9u, framer
.GetSynReplyMinimumSize());
4703 EXPECT_EQ(13u, framer
.GetRstStreamMinimumSize());
4704 EXPECT_EQ(9u, framer
.GetSettingsMinimumSize());
4705 EXPECT_EQ(17u, framer
.GetPingSize());
4706 EXPECT_EQ(17u, framer
.GetGoAwayMinimumSize());
4707 EXPECT_EQ(9u, framer
.GetHeadersMinimumSize());
4708 EXPECT_EQ(13u, framer
.GetWindowUpdateSize());
4709 EXPECT_EQ(9u, framer
.GetBlockedSize());
4710 EXPECT_EQ(13u, framer
.GetPushPromiseMinimumSize());
4711 EXPECT_EQ(18u, framer
.GetAltSvcMinimumSize());
4712 EXPECT_EQ(9u, framer
.GetFrameMinimumSize());
4713 EXPECT_EQ(16393u, framer
.GetFrameMaximumSize());
4714 EXPECT_EQ(16384u, framer
.GetDataFrameMaximumPayload());
4716 EXPECT_EQ(8u, framer
.GetDataFrameMinimumSize());
4717 EXPECT_EQ(8u, framer
.GetControlFrameHeaderSize());
4718 EXPECT_EQ(18u, framer
.GetSynStreamMinimumSize());
4719 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetSynReplyMinimumSize());
4720 EXPECT_EQ(16u, framer
.GetRstStreamMinimumSize());
4721 EXPECT_EQ(12u, framer
.GetSettingsMinimumSize());
4722 EXPECT_EQ(12u, framer
.GetPingSize());
4723 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer
.GetGoAwayMinimumSize());
4724 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer
.GetHeadersMinimumSize());
4725 EXPECT_EQ(16u, framer
.GetWindowUpdateSize());
4726 EXPECT_EQ(8u, framer
.GetFrameMinimumSize());
4727 EXPECT_EQ(16777223u, framer
.GetFrameMaximumSize());
4728 EXPECT_EQ(16777215u, framer
.GetDataFrameMaximumPayload());
4732 TEST_P(SpdyFramerTest
, StateToStringTest
) {
4733 EXPECT_STREQ("ERROR",
4734 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR
));
4735 EXPECT_STREQ("AUTO_RESET",
4736 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET
));
4737 EXPECT_STREQ("RESET",
4738 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET
));
4739 EXPECT_STREQ("READING_COMMON_HEADER",
4740 SpdyFramer::StateToString(
4741 SpdyFramer::SPDY_READING_COMMON_HEADER
));
4742 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4743 SpdyFramer::StateToString(
4744 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD
));
4745 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4746 SpdyFramer::StateToString(
4747 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD
));
4748 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4749 SpdyFramer::StateToString(
4750 SpdyFramer::SPDY_FORWARD_STREAM_FRAME
));
4751 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4752 SpdyFramer::StateToString(
4753 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
));
4754 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4755 SpdyFramer::StateToString(
4756 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK
));
4757 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4758 SpdyFramer::StateToString(
4759 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD
));
4760 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4761 SpdyFramer::StateToString(
4762 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD
));
4763 EXPECT_STREQ("UNKNOWN_STATE",
4764 SpdyFramer::StateToString(
4765 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD
+ 1));
4768 TEST_P(SpdyFramerTest
, ErrorCodeToStringTest
) {
4769 EXPECT_STREQ("NO_ERROR",
4770 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR
));
4771 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4772 SpdyFramer::ErrorCodeToString(
4773 SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4774 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4775 SpdyFramer::ErrorCodeToString(
4776 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4777 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4778 SpdyFramer::ErrorCodeToString(
4779 SpdyFramer::SPDY_ZLIB_INIT_FAILURE
));
4780 EXPECT_STREQ("UNSUPPORTED_VERSION",
4781 SpdyFramer::ErrorCodeToString(
4782 SpdyFramer::SPDY_UNSUPPORTED_VERSION
));
4783 EXPECT_STREQ("DECOMPRESS_FAILURE",
4784 SpdyFramer::ErrorCodeToString(
4785 SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4786 EXPECT_STREQ("COMPRESS_FAILURE",
4787 SpdyFramer::ErrorCodeToString(
4788 SpdyFramer::SPDY_COMPRESS_FAILURE
));
4789 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4790 SpdyFramer::ErrorCodeToString(
4791 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4792 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4793 SpdyFramer::ErrorCodeToString(
4794 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
));
4795 EXPECT_STREQ("UNKNOWN_ERROR",
4796 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR
));
4799 TEST_P(SpdyFramerTest
, StatusCodeToStringTest
) {
4800 EXPECT_STREQ("INVALID",
4801 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID
));
4802 EXPECT_STREQ("PROTOCOL_ERROR",
4803 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR
));
4804 EXPECT_STREQ("INVALID_STREAM",
4805 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM
));
4806 EXPECT_STREQ("REFUSED_STREAM",
4807 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM
));
4808 EXPECT_STREQ("UNSUPPORTED_VERSION",
4809 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION
));
4810 EXPECT_STREQ("CANCEL",
4811 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL
));
4812 EXPECT_STREQ("INTERNAL_ERROR",
4813 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR
));
4814 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4815 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR
));
4816 EXPECT_STREQ("UNKNOWN_STATUS",
4817 SpdyFramer::StatusCodeToString(-1));
4820 TEST_P(SpdyFramerTest
, FrameTypeToStringTest
) {
4821 EXPECT_STREQ("DATA",
4822 SpdyFramer::FrameTypeToString(DATA
));
4823 EXPECT_STREQ("SYN_STREAM",
4824 SpdyFramer::FrameTypeToString(SYN_STREAM
));
4825 EXPECT_STREQ("SYN_REPLY",
4826 SpdyFramer::FrameTypeToString(SYN_REPLY
));
4827 EXPECT_STREQ("RST_STREAM",
4828 SpdyFramer::FrameTypeToString(RST_STREAM
));
4829 EXPECT_STREQ("SETTINGS",
4830 SpdyFramer::FrameTypeToString(SETTINGS
));
4831 EXPECT_STREQ("PING",
4832 SpdyFramer::FrameTypeToString(PING
));
4833 EXPECT_STREQ("GOAWAY",
4834 SpdyFramer::FrameTypeToString(GOAWAY
));
4835 EXPECT_STREQ("HEADERS",
4836 SpdyFramer::FrameTypeToString(HEADERS
));
4837 EXPECT_STREQ("WINDOW_UPDATE",
4838 SpdyFramer::FrameTypeToString(WINDOW_UPDATE
));
4839 EXPECT_STREQ("PUSH_PROMISE",
4840 SpdyFramer::FrameTypeToString(PUSH_PROMISE
));
4841 EXPECT_STREQ("CREDENTIAL",
4842 SpdyFramer::FrameTypeToString(CREDENTIAL
));
4843 EXPECT_STREQ("CONTINUATION",
4844 SpdyFramer::FrameTypeToString(CONTINUATION
));
4847 TEST_P(SpdyFramerTest
, CatchProbableHttpResponse
) {
4849 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4853 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4854 SpdyFramer
framer(spdy_version_
);
4855 framer
.set_visitor(&visitor
);
4857 EXPECT_CALL(visitor
, OnError(_
));
4858 framer
.ProcessInput("HTTP/1.1", 8);
4859 EXPECT_TRUE(framer
.probable_http_response());
4860 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4861 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4862 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4865 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4866 SpdyFramer
framer(spdy_version_
);
4867 framer
.set_visitor(&visitor
);
4869 EXPECT_CALL(visitor
, OnError(_
));
4870 framer
.ProcessInput("HTTP/1.0", 8);
4871 EXPECT_TRUE(framer
.probable_http_response());
4872 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4873 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4874 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4878 TEST_P(SpdyFramerTest
, DataFrameFlagsV2V3
) {
4879 if (spdy_version_
> SPDY3
) {
4885 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4887 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4888 SpdyFramer
framer(spdy_version_
);
4889 framer
.set_visitor(&visitor
);
4891 SpdyDataIR
data_ir(1, StringPiece("hello", 5));
4892 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4893 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4895 if (flags
& ~DATA_FLAG_FIN
) {
4896 EXPECT_CALL(visitor
, OnError(_
));
4898 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
4899 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
4900 if (flags
& DATA_FLAG_FIN
) {
4901 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4905 framer
.ProcessInput(frame
->data(), frame
->size());
4906 if (flags
& ~DATA_FLAG_FIN
) {
4907 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4908 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
,
4909 framer
.error_code())
4910 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4912 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4913 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4914 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4916 } while (++flags
!= 0);
4919 TEST_P(SpdyFramerTest
, DataFrameFlagsV4
) {
4920 if (spdy_version_
<= SPDY3
) {
4924 uint8 valid_data_flags
= DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
|
4929 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4931 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4932 SpdyFramer
framer(spdy_version_
);
4933 framer
.set_visitor(&visitor
);
4935 SpdyDataIR
data_ir(1, StringPiece("hello", 5));
4936 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeData(data_ir
));
4937 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4939 if (flags
& ~valid_data_flags
) {
4940 EXPECT_CALL(visitor
, OnError(_
));
4942 EXPECT_CALL(visitor
, OnDataFrameHeader(1, 5, flags
& DATA_FLAG_FIN
));
4943 if (flags
& DATA_FLAG_PADDED
) {
4944 // The first byte of payload is parsed as padding length.
4945 EXPECT_CALL(visitor
, OnStreamPadding(_
, 1));
4946 // Expect Error since the frame ends prematurely.
4947 EXPECT_CALL(visitor
, OnError(_
));
4949 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 5, false));
4950 if (flags
& DATA_FLAG_FIN
) {
4951 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
4956 framer
.ProcessInput(frame
->data(), frame
->size());
4957 if ((flags
& ~valid_data_flags
) || (flags
& DATA_FLAG_PADDED
)) {
4958 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
4959 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
, framer
.error_code())
4960 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4962 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
4963 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
4964 << SpdyFramer::ErrorCodeToString(framer
.error_code());
4966 } while (++flags
!= 0);
4969 TEST_P(SpdyFramerTest
, SynStreamFrameFlags
) {
4970 if (!IsSpdy2() && !IsSpdy3()) {
4971 // SYN_STREAM not supported in SPDY>3
4976 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
4978 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
4979 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
4980 SpdyFramer
framer(spdy_version_
);
4981 framer
.set_visitor(&visitor
);
4982 framer
.set_debug_visitor(&debug_visitor
);
4984 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(8, SYN_STREAM
, _
, _
));
4986 SpdySynStreamIR
syn_stream(8);
4987 syn_stream
.set_associated_to_stream_id(3);
4988 syn_stream
.set_priority(1);
4989 syn_stream
.SetHeader("foo", "bar");
4990 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
4991 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
4993 if (flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
4994 EXPECT_CALL(visitor
, OnError(_
));
4996 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(8, SYN_STREAM
, _
));
4997 EXPECT_CALL(visitor
, OnSynStream(8, 3, 1, flags
& CONTROL_FLAG_FIN
,
4998 flags
& CONTROL_FLAG_UNIDIRECTIONAL
));
4999 EXPECT_CALL(visitor
, OnControlFrameHeaderData(8, _
, _
))
5000 .WillRepeatedly(testing::Return(true));
5001 if (flags
& DATA_FLAG_FIN
) {
5002 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
5004 // Do not close the stream if we are expecting a CONTINUATION frame.
5005 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
5009 framer
.ProcessInput(frame
->data(), frame
->size());
5010 if (flags
& ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
5011 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5012 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5013 framer
.error_code())
5014 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5016 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5017 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5018 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5020 } while (++flags
!= 0);
5023 TEST_P(SpdyFramerTest
, SynReplyFrameFlags
) {
5024 if (!IsSpdy2() && !IsSpdy3()) {
5025 // SYN_REPLY not supported in SPDY>3
5030 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5032 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5033 SpdyFramer
framer(spdy_version_
);
5034 framer
.set_visitor(&visitor
);
5036 SpdySynReplyIR
syn_reply(37);
5037 syn_reply
.SetHeader("foo", "bar");
5038 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynReply(syn_reply
));
5039 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5041 if (flags
& ~CONTROL_FLAG_FIN
) {
5042 EXPECT_CALL(visitor
, OnError(_
));
5044 EXPECT_CALL(visitor
, OnSynReply(37, flags
& CONTROL_FLAG_FIN
));
5045 EXPECT_CALL(visitor
, OnControlFrameHeaderData(37, _
, _
))
5046 .WillRepeatedly(testing::Return(true));
5047 if (flags
& DATA_FLAG_FIN
) {
5048 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
5052 framer
.ProcessInput(frame
->data(), frame
->size());
5053 if (flags
& ~CONTROL_FLAG_FIN
) {
5054 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5055 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5056 framer
.error_code())
5057 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5059 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5060 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5061 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5063 } while (++flags
!= 0);
5066 TEST_P(SpdyFramerTest
, RstStreamFrameFlags
) {
5069 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5071 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5072 SpdyFramer
framer(spdy_version_
);
5073 framer
.set_visitor(&visitor
);
5075 SpdyRstStreamIR
rst_stream(13, RST_STREAM_CANCEL
, "");
5076 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeRstStream(rst_stream
));
5077 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5080 EXPECT_CALL(visitor
, OnError(_
));
5082 EXPECT_CALL(visitor
, OnRstStream(13, RST_STREAM_CANCEL
));
5085 framer
.ProcessInput(frame
->data(), frame
->size());
5087 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5088 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5089 framer
.error_code())
5090 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5092 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5093 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5094 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5096 } while (++flags
!= 0);
5099 TEST_P(SpdyFramerTest
, SettingsFrameFlagsOldFormat
) {
5100 if (spdy_version_
> SPDY3
) { return; }
5103 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5105 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5106 SpdyFramer
framer(spdy_version_
);
5107 framer
.set_visitor(&visitor
);
5109 SpdySettingsIR settings_ir
;
5110 settings_ir
.AddSetting(SETTINGS_UPLOAD_BANDWIDTH
,
5114 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
5115 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5117 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
5118 EXPECT_CALL(visitor
, OnError(_
));
5120 EXPECT_CALL(visitor
, OnSettings(
5121 flags
& SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
));
5122 EXPECT_CALL(visitor
, OnSetting(SETTINGS_UPLOAD_BANDWIDTH
,
5123 SETTINGS_FLAG_NONE
, 54321));
5124 EXPECT_CALL(visitor
, OnSettingsEnd());
5127 framer
.ProcessInput(frame
->data(), frame
->size());
5128 if (flags
& ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
5129 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5130 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5131 framer
.error_code())
5132 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5134 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5135 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5136 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5138 } while (++flags
!= 0);
5141 TEST_P(SpdyFramerTest
, SettingsFrameFlags
) {
5142 if (spdy_version_
<= SPDY3
) { return; }
5145 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5147 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5148 SpdyFramer
framer(spdy_version_
);
5149 framer
.set_visitor(&visitor
);
5151 SpdySettingsIR settings_ir
;
5152 settings_ir
.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 0, 16);
5153 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSettings(settings_ir
));
5154 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5157 EXPECT_CALL(visitor
, OnError(_
));
5159 EXPECT_CALL(visitor
, OnSettings(flags
& SETTINGS_FLAG_ACK
));
5160 EXPECT_CALL(visitor
, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE
, 0, 16));
5161 EXPECT_CALL(visitor
, OnSettingsEnd());
5164 framer
.ProcessInput(frame
->data(), frame
->size());
5165 if (flags
& ~SETTINGS_FLAG_ACK
) {
5166 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5167 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5168 framer
.error_code())
5169 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5170 } else if (flags
& SETTINGS_FLAG_ACK
) {
5171 // The frame is invalid because ACK frames should have no payload.
5172 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5173 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5174 framer
.error_code())
5175 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5177 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5178 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5179 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5181 } while (++flags
!= 0);
5184 TEST_P(SpdyFramerTest
, GoawayFrameFlags
) {
5187 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5189 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5190 SpdyFramer
framer(spdy_version_
);
5191 framer
.set_visitor(&visitor
);
5193 SpdyGoAwayIR
goaway_ir(97, GOAWAY_OK
, "test");
5194 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeGoAway(goaway_ir
));
5195 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5198 EXPECT_CALL(visitor
, OnError(_
));
5200 EXPECT_CALL(visitor
, OnGoAway(97, GOAWAY_OK
));
5203 framer
.ProcessInput(frame
->data(), frame
->size());
5205 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5206 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5207 framer
.error_code())
5208 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5210 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5211 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5212 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5214 } while (++flags
!= 0);
5217 TEST_P(SpdyFramerTest
, HeadersFrameFlags
) {
5220 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5222 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5223 SpdyFramer
framer(spdy_version_
);
5224 framer
.set_visitor(&visitor
);
5226 SpdyHeadersIR
headers_ir(57);
5227 if (IsSpdy4() && (flags
& HEADERS_FLAG_PRIORITY
)) {
5228 headers_ir
.set_priority(3);
5229 headers_ir
.set_has_priority(true);
5231 headers_ir
.SetHeader("foo", "bar");
5232 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeHeaders(headers_ir
));
5233 uint8 set_flags
= flags
;
5235 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5236 // and implement framing.
5237 set_flags
&= ~HEADERS_FLAG_PADDED
;
5239 SetFrameFlags(frame
.get(), set_flags
, spdy_version_
);
5241 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
5242 EXPECT_CALL(visitor
, OnError(_
));
5243 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
5244 HEADERS_FLAG_END_HEADERS
|
5245 HEADERS_FLAG_END_SEGMENT
|
5246 HEADERS_FLAG_PADDED
|
5247 HEADERS_FLAG_PRIORITY
)) {
5248 EXPECT_CALL(visitor
, OnError(_
));
5250 if (spdy_version_
> SPDY3
&& flags
& HEADERS_FLAG_PRIORITY
) {
5251 EXPECT_CALL(visitor
, OnHeaders(57, // stream id
5252 true, // has priority?
5254 flags
& CONTROL_FLAG_FIN
, // fin?
5255 (flags
& HEADERS_FLAG_END_HEADERS
) ||
5256 !IsSpdy4())); // end headers?
5258 EXPECT_CALL(visitor
, OnHeaders(57, false, 0,
5259 flags
& CONTROL_FLAG_FIN
,
5260 (flags
& HEADERS_FLAG_END_HEADERS
) ||
5263 EXPECT_CALL(visitor
, OnControlFrameHeaderData(57, _
, _
))
5264 .WillRepeatedly(testing::Return(true));
5265 if (flags
& DATA_FLAG_FIN
&& (!IsSpdy4() ||
5266 flags
& HEADERS_FLAG_END_HEADERS
)) {
5267 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true));
5269 // Do not close the stream if we are expecting a CONTINUATION frame.
5270 EXPECT_CALL(visitor
, OnStreamFrameData(_
, _
, 0, true)).Times(0);
5274 framer
.ProcessInput(frame
->data(), frame
->size());
5275 if (!IsSpdy4() && flags
& ~CONTROL_FLAG_FIN
) {
5276 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5277 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5278 framer
.error_code())
5279 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5280 } else if (IsSpdy4() && flags
& ~(CONTROL_FLAG_FIN
|
5281 HEADERS_FLAG_END_HEADERS
|
5282 HEADERS_FLAG_END_SEGMENT
|
5283 HEADERS_FLAG_PADDED
|
5284 HEADERS_FLAG_PRIORITY
)) {
5285 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5286 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5287 framer
.error_code())
5288 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5289 } else if (IsSpdy4() && ~(flags
& HEADERS_FLAG_END_HEADERS
)) {
5290 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5291 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5292 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5294 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5295 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5296 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5298 } while (++flags
!= 0);
5301 TEST_P(SpdyFramerTest
, PingFrameFlags
) {
5304 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5306 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5307 SpdyFramer
framer(spdy_version_
);
5308 framer
.set_visitor(&visitor
);
5310 scoped_ptr
<SpdyFrame
> frame(framer
.SerializePing(SpdyPingIR(42)));
5311 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5313 if (spdy_version_
> SPDY3
&&
5314 flags
== PING_FLAG_ACK
) {
5315 EXPECT_CALL(visitor
, OnPing(42, true));
5316 } else if (flags
== 0) {
5317 EXPECT_CALL(visitor
, OnPing(42, false));
5319 EXPECT_CALL(visitor
, OnError(_
));
5322 framer
.ProcessInput(frame
->data(), frame
->size());
5323 if ((spdy_version_
> SPDY3
&& flags
== PING_FLAG_ACK
) ||
5325 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5326 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5327 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5329 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5330 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5331 framer
.error_code())
5332 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5334 } while (++flags
!= 0);
5337 TEST_P(SpdyFramerTest
, WindowUpdateFrameFlags
) {
5340 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5342 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5343 SpdyFramer
framer(spdy_version_
);
5344 framer
.set_visitor(&visitor
);
5346 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeWindowUpdate(
5347 SpdyWindowUpdateIR(4, 1024)));
5348 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5351 EXPECT_CALL(visitor
, OnError(_
));
5353 EXPECT_CALL(visitor
, OnWindowUpdate(4, 1024));
5356 framer
.ProcessInput(frame
->data(), frame
->size());
5358 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5359 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5360 framer
.error_code())
5361 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5363 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5364 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5365 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5367 } while (++flags
!= 0);
5370 TEST_P(SpdyFramerTest
, PushPromiseFrameFlags
) {
5371 if (spdy_version_
<= SPDY3
) {
5377 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5379 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5380 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
5381 SpdyFramer
framer(spdy_version_
);
5382 framer
.set_visitor(&visitor
);
5383 framer
.set_debug_visitor(&debug_visitor
);
5385 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, PUSH_PROMISE
, _
, _
));
5387 SpdyPushPromiseIR
push_promise(42, 57);
5388 push_promise
.SetHeader("foo", "bar");
5389 scoped_ptr
<SpdySerializedFrame
> frame(
5390 framer
.SerializePushPromise(push_promise
));
5391 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5392 // and implement framing.
5393 SetFrameFlags(frame
.get(), flags
& ~HEADERS_FLAG_PADDED
, spdy_version_
);
5395 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
| HEADERS_FLAG_PADDED
)) {
5396 EXPECT_CALL(visitor
, OnError(_
));
5398 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, PUSH_PROMISE
, _
));
5399 EXPECT_CALL(visitor
, OnPushPromise(42, 57,
5400 flags
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
));
5401 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
5402 .WillRepeatedly(testing::Return(true));
5405 framer
.ProcessInput(frame
->data(), frame
->size());
5406 if (flags
& ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
| HEADERS_FLAG_PADDED
)) {
5407 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5408 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5409 framer
.error_code())
5410 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5412 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5413 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5414 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5416 } while (++flags
!= 0);
5419 TEST_P(SpdyFramerTest
, ContinuationFrameFlags
) {
5420 if (spdy_version_
<= SPDY3
) {
5426 SCOPED_TRACE(testing::Message() << "Flags " << flags
);
5428 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5429 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
5430 SpdyFramer
framer(spdy_version_
);
5431 framer
.set_visitor(&visitor
);
5432 framer
.set_debug_visitor(&debug_visitor
);
5434 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(42, HEADERS
, _
, _
));
5435 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, HEADERS
, _
));
5436 EXPECT_CALL(visitor
, OnHeaders(42, false, 0, 0, false));
5437 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
5438 .WillRepeatedly(testing::Return(true));
5440 SpdyHeadersIR
headers_ir(42);
5441 headers_ir
.SetHeader("foo", "bar");
5442 scoped_ptr
<SpdyFrame
> frame0(framer
.SerializeHeaders(headers_ir
));
5443 SetFrameFlags(frame0
.get(), 0, spdy_version_
);
5445 SpdyContinuationIR
continuation(42);
5446 continuation
.SetHeader("foo", "bar");
5447 scoped_ptr
<SpdySerializedFrame
> frame(
5448 framer
.SerializeContinuation(continuation
));
5449 SetFrameFlags(frame
.get(), flags
, spdy_version_
);
5451 if (flags
& ~(HEADERS_FLAG_END_HEADERS
)) {
5452 EXPECT_CALL(visitor
, OnError(_
));
5454 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(42, CONTINUATION
, _
));
5455 EXPECT_CALL(visitor
, OnContinuation(42,
5456 flags
& HEADERS_FLAG_END_HEADERS
));
5457 EXPECT_CALL(visitor
, OnControlFrameHeaderData(42, _
, _
))
5458 .WillRepeatedly(testing::Return(true));
5461 framer
.ProcessInput(frame0
->data(), frame0
->size());
5462 framer
.ProcessInput(frame
->data(), frame
->size());
5463 if (flags
& ~(HEADERS_FLAG_END_HEADERS
)) {
5464 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, framer
.state());
5465 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS
,
5466 framer
.error_code())
5467 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5469 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5470 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5471 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5473 } while (++flags
!= 0);
5476 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5478 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5480 TEST_P(SpdyFramerTest
, EmptySynStream
) {
5481 if (!IsSpdy2() && !IsSpdy3()) {
5482 // SYN_STREAM not supported in SPDY>3.
5485 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5486 testing::StrictMock
<test::MockDebugVisitor
> debug_visitor
;
5487 SpdyFramer
framer(spdy_version_
);
5488 framer
.set_visitor(&visitor
);
5489 framer
.set_debug_visitor(&debug_visitor
);
5491 EXPECT_CALL(debug_visitor
, OnSendCompressedFrame(1, SYN_STREAM
, _
, _
));
5493 SpdySynStreamIR
syn_stream(1);
5494 syn_stream
.set_priority(1);
5495 scoped_ptr
<SpdyFrame
> frame(framer
.SerializeSynStream(syn_stream
));
5496 // Adjust size to remove the name/value block.
5499 framer
.GetSynStreamMinimumSize() - framer
.GetControlFrameHeaderSize(),
5502 EXPECT_CALL(debug_visitor
, OnReceiveCompressedFrame(1, SYN_STREAM
, _
));
5503 EXPECT_CALL(visitor
, OnSynStream(1, 0, 1, false, false));
5504 EXPECT_CALL(visitor
, OnControlFrameHeaderData(1, NULL
, 0));
5506 framer
.ProcessInput(frame
->data(), framer
.GetSynStreamMinimumSize());
5507 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5508 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5509 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5512 TEST_P(SpdyFramerTest
, SettingsFlagsAndId
) {
5513 const uint32 kId
= 0x020304;
5514 const uint32 kFlags
= 0x01;
5515 const uint32 kWireFormat
= htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5517 SettingsFlagsAndId id_and_flags
=
5518 SettingsFlagsAndId::FromWireFormat(spdy_version_
, kWireFormat
);
5519 EXPECT_EQ(kId
, id_and_flags
.id());
5520 EXPECT_EQ(kFlags
, id_and_flags
.flags());
5521 EXPECT_EQ(kWireFormat
, id_and_flags
.GetWireFormat(spdy_version_
));
5524 // Test handling of a RST_STREAM with out-of-bounds status codes.
5525 TEST_P(SpdyFramerTest
, RstStreamStatusBounds
) {
5526 const unsigned char kRstStreamStatusTooLow
= 0x00;
5527 const unsigned char kRstStreamStatusTooHigh
= 0xff;
5528 const unsigned char kV3RstStreamInvalid
[] = {
5529 0x80, spdy_version_ch_
, 0x00, 0x03,
5530 0x00, 0x00, 0x00, 0x08,
5531 0x00, 0x00, 0x00, 0x01,
5532 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5534 const unsigned char kV4RstStreamInvalid
[] = {
5535 0x00, 0x00, 0x04, 0x03,
5536 0x00, 0x00, 0x00, 0x00,
5537 0x01, 0x00, 0x00, 0x00,
5538 kRstStreamStatusTooLow
5541 const unsigned char kV3RstStreamNumStatusCodes
[] = {
5542 0x80, spdy_version_ch_
, 0x00, 0x03,
5543 0x00, 0x00, 0x00, 0x08,
5544 0x00, 0x00, 0x00, 0x01,
5545 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5547 const unsigned char kV4RstStreamNumStatusCodes
[] = {
5548 0x00, 0x00, 0x04, 0x03,
5549 0x00, 0x00, 0x00, 0x00,
5550 0x01, 0x00, 0x00, 0x00,
5551 kRstStreamStatusTooHigh
5554 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5555 SpdyFramer
framer(spdy_version_
);
5556 framer
.set_visitor(&visitor
);
5559 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INTERNAL_ERROR
));
5560 framer
.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid
),
5561 arraysize(kV4RstStreamInvalid
));
5563 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
5564 framer
.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid
),
5565 arraysize(kV3RstStreamInvalid
));
5567 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5568 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5569 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5575 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INTERNAL_ERROR
));
5576 framer
.ProcessInput(
5577 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes
),
5578 arraysize(kV4RstStreamNumStatusCodes
));
5580 EXPECT_CALL(visitor
, OnRstStream(1, RST_STREAM_INVALID
));
5581 framer
.ProcessInput(
5582 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes
),
5583 arraysize(kV3RstStreamNumStatusCodes
));
5585 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5586 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5587 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5590 // Test handling of GOAWAY frames with out-of-bounds status code.
5591 TEST_P(SpdyFramerTest
, GoAwayStatusBounds
) {
5592 if (spdy_version_
<= SPDY2
) {
5595 SpdyFramer
framer(spdy_version_
);
5597 const unsigned char kV3FrameData
[] = {
5598 0x80, spdy_version_ch_
, 0x00, 0x07,
5599 0x00, 0x00, 0x00, 0x08,
5600 0x00, 0x00, 0x00, 0x01, // Stream Id
5601 0xff, 0xff, 0xff, 0xff, // Status
5603 const unsigned char kV4FrameData
[] = {
5604 0x00, 0x00, 0x0a, 0x07,
5605 0x00, 0x00, 0x00, 0x00,
5606 0x00, 0x00, 0x00, 0x00, // Stream id
5607 0x01, 0xff, 0xff, 0xff, // Status
5608 0xff, 0x47, 0x41, // Opaque Description
5610 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5611 framer
.set_visitor(&visitor
);
5614 EXPECT_CALL(visitor
, OnGoAway(1, GOAWAY_OK
));
5615 framer
.ProcessInput(reinterpret_cast<const char*>(kV3FrameData
),
5616 arraysize(kV3FrameData
));
5618 EXPECT_CALL(visitor
, OnGoAway(1, GOAWAY_INTERNAL_ERROR
));
5619 framer
.ProcessInput(reinterpret_cast<const char*>(kV4FrameData
),
5620 arraysize(kV4FrameData
));
5622 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5623 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5624 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5627 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5628 TEST_P(SpdyFramerTest
, GoAwayStreamIdBounds
) {
5629 const unsigned char kV2FrameData
[] = {
5630 0x80, spdy_version_ch_
, 0x00, 0x07,
5631 0x00, 0x00, 0x00, 0x04,
5632 0xff, 0xff, 0xff, 0xff,
5634 const unsigned char kV3FrameData
[] = {
5635 0x80, spdy_version_ch_
, 0x00, 0x07,
5636 0x00, 0x00, 0x00, 0x08,
5637 0xff, 0xff, 0xff, 0xff,
5638 0x00, 0x00, 0x00, 0x00,
5640 const unsigned char kV4FrameData
[] = {
5641 0x00, 0x00, 0x08, 0x07,
5642 0x00, 0x00, 0x00, 0x00,
5643 0x00, 0xff, 0xff, 0xff,
5644 0xff, 0x00, 0x00, 0x00,
5648 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5649 SpdyFramer
framer(spdy_version_
);
5650 framer
.set_visitor(&visitor
);
5652 EXPECT_CALL(visitor
, OnGoAway(0x7fffffff, GOAWAY_OK
));
5654 framer
.ProcessInput(reinterpret_cast<const char*>(kV2FrameData
),
5655 arraysize(kV2FrameData
));
5656 } else if (IsSpdy3()) {
5657 framer
.ProcessInput(reinterpret_cast<const char*>(kV3FrameData
),
5658 arraysize(kV3FrameData
));
5660 framer
.ProcessInput(reinterpret_cast<const char*>(kV4FrameData
),
5661 arraysize(kV4FrameData
));
5663 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5664 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5665 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5668 TEST_P(SpdyFramerTest
, OnBlocked
) {
5669 if (spdy_version_
<= SPDY3
) {
5673 const SpdyStreamId kStreamId
= 0;
5675 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5676 SpdyFramer
framer(spdy_version_
);
5677 framer
.set_visitor(&visitor
);
5679 EXPECT_CALL(visitor
, OnBlocked(kStreamId
));
5681 SpdyBlockedIR
blocked_ir(0);
5682 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(blocked_ir
));
5683 framer
.ProcessInput(frame
->data(), framer
.GetBlockedSize());
5685 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5686 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5687 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5690 TEST_P(SpdyFramerTest
, OnAltSvc
) {
5691 if (spdy_version_
<= SPDY3
) {
5695 const SpdyStreamId kStreamId
= 1;
5697 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5698 SpdyFramer
framer(spdy_version_
);
5699 framer
.set_visitor(&visitor
);
5701 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
,
5706 StringPiece("o1")));
5708 SpdyAltSvcIR
altsvc_ir(1);
5709 altsvc_ir
.set_max_age(10);
5710 altsvc_ir
.set_port(443);
5711 altsvc_ir
.set_protocol_id("pid");
5712 altsvc_ir
.set_host("h1");
5713 altsvc_ir
.set_origin("o1");
5714 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5715 framer
.ProcessInput(frame
->data(), framer
.GetAltSvcMinimumSize() +
5716 altsvc_ir
.protocol_id().length() +
5717 altsvc_ir
.host().length() +
5718 altsvc_ir
.origin().length());
5720 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5721 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5722 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5725 TEST_P(SpdyFramerTest
, OnAltSvcNoOrigin
) {
5726 if (spdy_version_
<= SPDY3
) {
5730 const SpdyStreamId kStreamId
= 1;
5732 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5733 SpdyFramer
framer(spdy_version_
);
5734 framer
.set_visitor(&visitor
);
5736 EXPECT_CALL(visitor
, OnAltSvc(kStreamId
,
5743 SpdyAltSvcIR
altsvc_ir(1);
5744 altsvc_ir
.set_max_age(10);
5745 altsvc_ir
.set_port(443);
5746 altsvc_ir
.set_protocol_id("pid");
5747 altsvc_ir
.set_host("h1");
5748 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializeFrame(altsvc_ir
));
5749 framer
.ProcessInput(frame
->data(), framer
.GetAltSvcMinimumSize() +
5750 altsvc_ir
.protocol_id().length() +
5751 altsvc_ir
.host().length());
5753 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5754 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5755 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5758 TEST_P(SpdyFramerTest
, OnAltSvcBadLengths
) {
5759 if (spdy_version_
<= SPDY3
) {
5763 const unsigned char kType
= static_cast<unsigned char>(
5764 SpdyConstants::SerializeFrameType(spdy_version_
, ALTSVC
));
5766 TestSpdyVisitor
visitor(spdy_version_
);
5767 SpdyFramer
framer(spdy_version_
);
5768 framer
.set_visitor(&visitor
);
5770 const unsigned char kFrameDataLargePIDLen
[] = {
5771 0x00, 0x00, 0x17, kType
, 0x00,
5772 0x00, 0x00, 0x00, 0x03,
5773 0x00, 0x00, 0x00, 0x05,
5774 0x01, 0xbb, 0x00, 0x05, // Port = 443
5775 'p', 'i', 'd', '1', // Protocol-ID
5776 0x04, 'h', 'o', 's',
5781 visitor
.SimulateInFramer(kFrameDataLargePIDLen
,
5782 sizeof(kFrameDataLargePIDLen
));
5783 EXPECT_EQ(1, visitor
.error_count_
);
5784 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5785 visitor
.framer_
.error_code());
5789 TestSpdyVisitor
visitor(spdy_version_
);
5790 SpdyFramer
framer(spdy_version_
);
5791 framer
.set_visitor(&visitor
);
5792 const unsigned char kFrameDataPIDLenLargerThanFrame
[] = {
5793 0x00, 0x00, 0x17, kType
, 0x00,
5794 0x00, 0x00, 0x00, 0x03,
5795 0x00, 0x00, 0x00, 0x05,
5796 0x01, 0xbb, 0x00, 0x99, // Port = 443
5797 'p', 'i', 'd', '1', // Protocol-ID
5798 0x04, 'h', 'o', 's',
5803 visitor
.SimulateInFramer(kFrameDataPIDLenLargerThanFrame
,
5804 sizeof(kFrameDataPIDLenLargerThanFrame
));
5805 EXPECT_EQ(1, visitor
.error_count_
);
5806 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5807 visitor
.framer_
.error_code());
5811 TestSpdyVisitor
visitor(spdy_version_
);
5812 SpdyFramer
framer(spdy_version_
);
5813 framer
.set_visitor(&visitor
);
5815 const unsigned char kFrameDataLargeHostLen
[] = {
5816 0x00, 0x00, 0x17, kType
, 0x00,
5817 0x00, 0x00, 0x00, 0x03,
5818 0x00, 0x00, 0x00, 0x05,
5819 0x01, 0xbb, 0x00, 0x04, // Port = 443
5820 'p', 'i', 'd', '1', // Protocol-ID
5821 0x0f, 'h', 'o', 's',
5826 visitor
.SimulateInFramer(kFrameDataLargeHostLen
,
5827 sizeof(kFrameDataLargeHostLen
));
5828 EXPECT_EQ(1, visitor
.error_count_
);
5829 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5830 visitor
.framer_
.error_code());
5834 TestSpdyVisitor
visitor(spdy_version_
);
5835 SpdyFramer
framer(spdy_version_
);
5836 framer
.set_visitor(&visitor
);
5837 const unsigned char kFrameDataSmallPIDLen
[] = {
5838 0x00, 0x00, 0x17, kType
, 0x00,
5839 0x00, 0x00, 0x00, 0x03,
5840 0x00, 0x00, 0x00, 0x05,
5841 0x01, 0xbb, 0x00, 0x01, // Port = 443
5842 'p', 'i', 'd', '1', // Protocol-ID
5843 0x04, 'h', 'o', 's',
5848 visitor
.SimulateInFramer(kFrameDataSmallPIDLen
,
5849 sizeof(kFrameDataSmallPIDLen
));
5850 EXPECT_EQ(1, visitor
.error_count_
);
5851 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5852 visitor
.framer_
.error_code());
5856 // Tests handling of ALTSVC frames delivered in small chunks.
5857 TEST_P(SpdyFramerTest
, ReadChunkedAltSvcFrame
) {
5858 if (spdy_version_
<= SPDY3
) {
5861 SpdyFramer
framer(spdy_version_
);
5862 SpdyAltSvcIR
altsvc_ir(1);
5863 altsvc_ir
.set_max_age(20);
5864 altsvc_ir
.set_port(443);
5865 altsvc_ir
.set_protocol_id("protocolid");
5866 altsvc_ir
.set_host("hostname");
5868 scoped_ptr
<SpdyFrame
> control_frame(framer
.SerializeAltSvc(altsvc_ir
));
5869 TestSpdyVisitor
visitor(spdy_version_
);
5870 visitor
.use_compression_
= false;
5872 // Read data in small chunks.
5873 size_t framed_data
= 0;
5874 size_t unframed_data
= control_frame
->size();
5875 size_t kReadChunkSize
= 5; // Read five bytes at a time.
5876 while (unframed_data
> 0) {
5877 size_t to_read
= std::min(kReadChunkSize
, unframed_data
);
5878 visitor
.SimulateInFramer(
5879 reinterpret_cast<unsigned char*>(control_frame
->data() + framed_data
),
5881 unframed_data
-= to_read
;
5882 framed_data
+= to_read
;
5884 EXPECT_EQ(0, visitor
.error_count_
);
5885 EXPECT_EQ(1, visitor
.altsvc_count_
);
5886 EXPECT_EQ(20u, visitor
.test_altsvc_ir_
.max_age());
5887 EXPECT_EQ(443u, visitor
.test_altsvc_ir_
.port());
5888 EXPECT_EQ("protocolid", visitor
.test_altsvc_ir_
.protocol_id());
5889 EXPECT_EQ("hostname", visitor
.test_altsvc_ir_
.host());
5892 // Tests handling of PRIORITY frames.
5893 TEST_P(SpdyFramerTest
, ReadPriority
) {
5894 if (spdy_version_
<= SPDY3
) {
5897 SpdyFramer
framer(spdy_version_
);
5898 SpdyPriorityIR
priority(3, 1, 255, false);
5899 scoped_ptr
<SpdySerializedFrame
> frame(framer
.SerializePriority(priority
));
5900 testing::StrictMock
<test::MockSpdyFramerVisitor
> visitor
;
5901 framer
.set_visitor(&visitor
);
5902 EXPECT_CALL(visitor
, OnPriority(3, 1, 255, false));
5903 framer
.ProcessInput(frame
->data(), frame
->size());
5905 EXPECT_EQ(SpdyFramer::SPDY_RESET
, framer
.state());
5906 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR
, framer
.error_code())
5907 << SpdyFramer::ErrorCodeToString(framer
.error_code());
5908 // TODO(mlavan): once we actually maintain a priority tree,
5909 // check that state is adjusted correctly.
5912 TEST_P(SpdyFramerTest
, PriorityWeightMapping
) {
5913 if (spdy_version_
<= SPDY3
) {
5916 SpdyFramer
framer(spdy_version_
);
5918 EXPECT_EQ(255u, framer
.MapPriorityToWeight(0));
5919 EXPECT_EQ(219u, framer
.MapPriorityToWeight(1));
5920 EXPECT_EQ(182u, framer
.MapPriorityToWeight(2));
5921 EXPECT_EQ(146u, framer
.MapPriorityToWeight(3));
5922 EXPECT_EQ(109u, framer
.MapPriorityToWeight(4));
5923 EXPECT_EQ(73u, framer
.MapPriorityToWeight(5));
5924 EXPECT_EQ(36u, framer
.MapPriorityToWeight(6));
5925 EXPECT_EQ(0u, framer
.MapPriorityToWeight(7));
5927 EXPECT_EQ(0u, framer
.MapWeightToPriority(255));
5928 EXPECT_EQ(0u, framer
.MapWeightToPriority(220));
5929 EXPECT_EQ(1u, framer
.MapWeightToPriority(219));
5930 EXPECT_EQ(1u, framer
.MapWeightToPriority(183));
5931 EXPECT_EQ(2u, framer
.MapWeightToPriority(182));
5932 EXPECT_EQ(2u, framer
.MapWeightToPriority(147));
5933 EXPECT_EQ(3u, framer
.MapWeightToPriority(146));
5934 EXPECT_EQ(3u, framer
.MapWeightToPriority(110));
5935 EXPECT_EQ(4u, framer
.MapWeightToPriority(109));
5936 EXPECT_EQ(4u, framer
.MapWeightToPriority(74));
5937 EXPECT_EQ(5u, framer
.MapWeightToPriority(73));
5938 EXPECT_EQ(5u, framer
.MapWeightToPriority(37));
5939 EXPECT_EQ(6u, framer
.MapWeightToPriority(36));
5940 EXPECT_EQ(6u, framer
.MapWeightToPriority(1));
5941 EXPECT_EQ(7u, framer
.MapWeightToPriority(0));
5944 // Tests handling of PRIORITY frame with incorrect size.
5945 TEST_P(SpdyFramerTest
, ReadIncorrectlySizedPriority
) {
5946 if (spdy_version_
<= SPDY3
) {
5950 // PRIORITY frame of size 4, which isn't correct.
5951 const unsigned char kFrameData
[] = {
5952 0x00, 0x00, 0x04, 0x02, 0x00,
5953 0x00, 0x00, 0x00, 0x03,
5954 0x00, 0x00, 0x00, 0x01,
5957 TestSpdyVisitor
visitor(spdy_version_
);
5958 visitor
.SimulateInFramer(kFrameData
, sizeof(kFrameData
));
5960 EXPECT_EQ(SpdyFramer::SPDY_ERROR
, visitor
.framer_
.state());
5961 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
,
5962 visitor
.framer_
.error_code())
5963 << SpdyFramer::ErrorCodeToString(visitor
.framer_
.error_code());