1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
21 using base::StringPiece;
25 using std::numeric_limits;
26 using testing::ElementsAre;
34 static const size_t kMaxDecompressedSize = 1024;
36 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
38 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
43 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
48 class SpdyFramerTestUtil {
50 // Decompress a single frame using the decompression context held by
51 // the SpdyFramer. The implemention is meant for use only in tests
52 // and will CHECK fail if the input is anything other than a single,
53 // well-formed compressed frame.
55 // Returns a new decompressed SpdyFrame.
56 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
57 SpdyFramer* framer, const SpdyFrameType& frame) {
58 DecompressionVisitor visitor(framer->protocol_version());
59 framer->set_visitor(&visitor);
60 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
61 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
62 framer->set_visitor(NULL);
64 char* buffer = visitor.ReleaseBuffer();
65 CHECK(buffer != NULL);
66 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
67 SetFrameLength(decompressed_frame,
68 visitor.size() - framer->GetControlFrameHeaderSize(),
69 framer->protocol_version());
70 return decompressed_frame;
73 class DecompressionVisitor : public SpdyFramerVisitorInterface {
75 explicit DecompressionVisitor(SpdyMajorVersion version)
76 : version_(version), size_(0), finished_(false) {}
79 CHECK(buffer_.get() == NULL);
82 buffer_.reset(new char[kMaxDecompressedSize]);
85 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
86 void OnDataFrameHeader(SpdyStreamId stream_id,
89 LOG(FATAL) << "Unexpected data frame header";
91 void OnStreamFrameData(SpdyStreamId stream_id,
98 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
99 const char* header_data,
100 size_t len) override {
101 CHECK(buffer_.get() != NULL);
102 CHECK_GE(kMaxDecompressedSize, size_ + len);
105 memcpy(buffer_.get() + size_, header_data, len);
114 void OnSynStream(SpdyStreamId stream_id,
115 SpdyStreamId associated_stream_id,
116 SpdyPriority priority,
118 bool unidirectional) override {
119 SpdyFramer framer(version_);
120 framer.set_enable_compression(false);
121 SpdySynStreamIR syn_stream(stream_id);
122 syn_stream.set_associated_to_stream_id(associated_stream_id);
123 syn_stream.set_priority(priority);
124 syn_stream.set_fin(fin);
125 syn_stream.set_unidirectional(unidirectional);
126 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
128 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
129 size_ += framer.GetSynStreamMinimumSize();
132 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
133 SpdyFramer framer(version_);
134 framer.set_enable_compression(false);
135 SpdyHeadersIR headers(stream_id);
136 headers.set_fin(fin);
137 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
139 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
140 size_ += framer.GetSynStreamMinimumSize();
143 void OnRstStream(SpdyStreamId stream_id,
144 SpdyRstStreamStatus status) override {
147 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
150 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
151 void OnSettingsEnd() override { LOG(FATAL); }
152 void OnGoAway(SpdyStreamId last_accepted_stream_id,
153 SpdyGoAwayStatus status) override {
157 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
158 SpdyPriority priority, bool fin, bool end) override {
159 SpdyFramer framer(version_);
160 framer.set_enable_compression(false);
161 SpdyHeadersIR headers(stream_id);
162 headers.set_has_priority(has_priority);
163 if (headers.has_priority()) {
164 headers.set_priority(priority);
166 headers.set_fin(fin);
167 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
169 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
170 size_ += framer.GetHeadersMinimumSize();
173 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
177 void OnPushPromise(SpdyStreamId stream_id,
178 SpdyStreamId promised_stream_id,
180 SpdyFramer framer(version_);
181 framer.set_enable_compression(false);
182 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
183 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
185 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
186 size_ += framer.GetPushPromiseMinimumSize();
189 void OnContinuation(SpdyStreamId stream_id, bool end) override {
193 void OnPriority(SpdyStreamId stream_id,
194 SpdyStreamId parent_stream_id,
196 bool exclusive) override {
200 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
205 char* ReleaseBuffer() {
207 return buffer_.release();
210 void OnWindowUpdate(SpdyStreamId stream_id,
211 uint32 delta_window_size) override {
215 size_t size() const {
221 SpdyMajorVersion version_;
222 scoped_ptr<char[]> buffer_;
226 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
230 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
233 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
234 public SpdyFramerDebugVisitorInterface {
236 // This is larger than our max frame size because header blocks that
237 // are too long can spill over into CONTINUATION frames.
238 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
240 explicit TestSpdyVisitor(SpdyMajorVersion version)
242 use_compression_(false),
245 syn_reply_frame_count_(0),
246 headers_frame_count_(0),
247 push_promise_frame_count_(0),
250 settings_ack_sent_(0),
251 settings_ack_received_(0),
252 continuation_count_(0),
256 on_unknown_frame_result_(false),
257 last_window_update_stream_(0),
258 last_window_update_delta_(0),
259 last_push_promise_stream_(0),
260 last_push_promise_promised_stream_(0),
265 zero_length_data_frame_count_(0),
266 control_frame_header_data_count_(0),
267 zero_length_control_frame_header_data_count_(0),
268 data_frame_count_(0),
269 last_payload_len_(0),
271 header_buffer_(new char[kDefaultHeaderBufferSize]),
272 header_buffer_length_(0),
273 header_buffer_size_(kDefaultHeaderBufferSize),
274 header_stream_id_(static_cast<SpdyStreamId>(-1)),
275 header_control_type_(DATA),
276 header_buffer_valid_(false) {}
278 void OnError(SpdyFramer* f) override {
279 LOG(INFO) << "SpdyFramer Error: "
280 << SpdyFramer::ErrorCodeToString(f->error_code());
284 void OnDataFrameHeader(SpdyStreamId stream_id,
288 header_stream_id_ = stream_id;
291 void OnStreamFrameData(SpdyStreamId stream_id,
295 EXPECT_EQ(header_stream_id_, stream_id);
297 ++zero_length_data_frame_count_;
300 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
302 for (size_t i = 0 ; i < len; ++i) {
303 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
306 std::cerr << "\", " << len << ")\n";
309 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
310 const char* header_data,
311 size_t len) override {
312 ++control_frame_header_data_count_;
313 CHECK_EQ(header_stream_id_, stream_id);
315 ++zero_length_control_frame_header_data_count_;
316 // Indicates end-of-header-block.
318 CHECK(header_buffer_valid_);
319 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
320 header_buffer_.get(), header_buffer_length_, &headers_);
321 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
322 << "Check failed: header_buffer_length_ == parsed_length "
323 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
326 const size_t available = header_buffer_size_ - header_buffer_length_;
327 if (len > available) {
328 header_buffer_valid_ = false;
331 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
332 header_buffer_length_ += len;
336 void OnSynStream(SpdyStreamId stream_id,
337 SpdyStreamId associated_stream_id,
338 SpdyPriority priority,
340 bool unidirectional) override {
342 if (framer_.protocol_version() > SPDY3) {
343 InitHeaderStreaming(HEADERS, stream_id);
345 InitHeaderStreaming(SYN_STREAM, stream_id);
352 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
353 ++syn_reply_frame_count_;
354 if (framer_.protocol_version() > SPDY3) {
355 InitHeaderStreaming(HEADERS, stream_id);
357 InitHeaderStreaming(SYN_REPLY, stream_id);
364 void OnRstStream(SpdyStreamId stream_id,
365 SpdyRstStreamStatus status) override {
369 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
370 if ((rst_stream_data != NULL) && (len > 0)) {
371 fin_opaque_data_ += std::string(rst_stream_data, len);
376 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
380 void OnSettingsAck() override {
381 DCHECK_LT(SPDY3, framer_.protocol_version());
382 ++settings_ack_received_;
385 void OnSettingsEnd() override {
386 if (framer_.protocol_version() <= SPDY3) { return; }
387 ++settings_ack_sent_;
390 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
392 void OnGoAway(SpdyStreamId last_accepted_stream_id,
393 SpdyGoAwayStatus status) override {
397 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
398 SpdyPriority priority, bool fin, bool end) override {
399 ++headers_frame_count_;
400 InitHeaderStreaming(HEADERS, stream_id);
406 void OnWindowUpdate(SpdyStreamId stream_id,
407 uint32 delta_window_size) override {
408 last_window_update_stream_ = stream_id;
409 last_window_update_delta_ = delta_window_size;
412 void OnPushPromise(SpdyStreamId stream_id,
413 SpdyStreamId promised_stream_id,
415 ++push_promise_frame_count_;
416 InitHeaderStreaming(PUSH_PROMISE, stream_id);
417 last_push_promise_stream_ = stream_id;
418 last_push_promise_promised_stream_ = promised_stream_id;
421 void OnContinuation(SpdyStreamId stream_id, bool end) override {
422 ++continuation_count_;
425 void OnAltSvc(SpdyStreamId stream_id,
428 StringPiece protocol_id,
430 StringPiece origin) override {
431 test_altsvc_ir_.set_stream_id(stream_id);
432 test_altsvc_ir_.set_max_age(max_age);
433 test_altsvc_ir_.set_port(port);
434 test_altsvc_ir_.set_protocol_id(protocol_id.as_string());
435 test_altsvc_ir_.set_host(host.as_string());
436 if (origin.length() > 0) {
437 test_altsvc_ir_.set_origin(origin.as_string());
442 void OnPriority(SpdyStreamId stream_id,
443 SpdyStreamId parent_stream_id,
445 bool exclusive) override {
449 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
450 DLOG(INFO) << "Unknown frame type " << frame_type;
451 return on_unknown_frame_result_;
454 void OnSendCompressedFrame(SpdyStreamId stream_id,
457 size_t frame_len) override {
458 last_payload_len_ = payload_len;
459 last_frame_len_ = frame_len;
462 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
464 size_t frame_len) override {
465 last_frame_len_ = frame_len;
468 // Convenience function which runs a framer simulation with particular input.
469 void SimulateInFramer(const unsigned char* input, size_t size) {
470 framer_.set_enable_compression(use_compression_);
471 framer_.set_visitor(this);
472 size_t input_remaining = size;
473 const char* input_ptr = reinterpret_cast<const char*>(input);
474 while (input_remaining > 0 &&
475 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
476 // To make the tests more interesting, we feed random (amd small) chunks
477 // into the framer. This simulates getting strange-sized reads from
479 const size_t kMaxReadSize = 32;
481 (rand() % min(input_remaining, kMaxReadSize)) + 1;
482 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
483 input_remaining -= bytes_processed;
484 input_ptr += bytes_processed;
488 void InitHeaderStreaming(SpdyFrameType header_control_type,
489 SpdyStreamId stream_id) {
490 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
491 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
492 header_control_type))) {
493 DLOG(FATAL) << "Attempted to init header streaming with "
494 << "invalid control frame type: "
495 << header_control_type;
497 memset(header_buffer_.get(), 0, header_buffer_size_);
498 header_buffer_length_ = 0;
499 header_stream_id_ = stream_id;
500 header_control_type_ = header_control_type;
501 header_buffer_valid_ = true;
502 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
505 // Override the default buffer size (16K). Call before using the framer!
506 void set_header_buffer_size(size_t header_buffer_size) {
507 header_buffer_size_ = header_buffer_size;
508 header_buffer_.reset(new char[header_buffer_size]);
511 // Largest control frame that the SPDY implementation sends, including the
512 // size of the header.
513 static size_t sent_control_frame_max_size() {
514 return SpdyFramer::kMaxControlFrameSize;
517 static size_t header_data_chunk_max_size() {
518 return SpdyFramer::kHeaderDataChunkMaxSize;
522 bool use_compression_;
524 // Counters from the visitor callbacks.
526 int syn_frame_count_;
527 int syn_reply_frame_count_;
528 int headers_frame_count_;
529 int push_promise_frame_count_;
532 int settings_ack_sent_;
533 int settings_ack_received_;
534 int continuation_count_;
537 SpdyAltSvcIR test_altsvc_ir_;
538 bool on_unknown_frame_result_;
539 SpdyStreamId last_window_update_stream_;
540 uint32 last_window_update_delta_;
541 SpdyStreamId last_push_promise_stream_;
542 SpdyStreamId last_push_promise_promised_stream_;
544 int fin_frame_count_; // The count of RST_STREAM type frames received.
545 std::string fin_opaque_data_;
546 int fin_flag_count_; // The count of frames with the FIN flag set.
547 int zero_length_data_frame_count_; // The count of zero-length data frames.
548 int control_frame_header_data_count_; // The count of chunks received.
549 // The count of zero-length control frame header data chunks received.
550 int zero_length_control_frame_header_data_count_;
551 int data_frame_count_;
552 size_t last_payload_len_;
553 size_t last_frame_len_;
555 // Header block streaming state:
556 scoped_ptr<char[]> header_buffer_;
557 size_t header_buffer_length_;
558 size_t header_buffer_size_;
559 SpdyStreamId header_stream_id_;
560 SpdyFrameType header_control_type_;
561 bool header_buffer_valid_;
562 SpdyHeaderBlock headers_;
565 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
566 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
567 const SpdyFramer& framer) {
568 SpdyFrameReader reader(frame->data(), frame->size());
569 if (framer.protocol_version() > SPDY3) {
570 reader.Seek(3); // Seek past the frame length.
572 reader.Seek(2); // Seek past the frame length.
574 SpdyFrameType frame_type;
575 if (framer.protocol_version() > SPDY3) {
576 uint8 serialized_type;
577 reader.ReadUInt8(&serialized_type);
578 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
580 DCHECK_EQ(HEADERS, frame_type);
582 reader.ReadUInt8(&flags);
583 if (flags & HEADERS_FLAG_PRIORITY) {
584 frame_type = SYN_STREAM;
587 uint16 serialized_type;
588 reader.ReadUInt16(&serialized_type);
589 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
591 DCHECK(frame_type == HEADERS ||
592 frame_type == SYN_STREAM) << frame_type;
595 if (frame_type == SYN_STREAM) {
596 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
597 frame->size() - framer.GetSynStreamMinimumSize());
599 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
600 frame->size() - framer.GetHeadersMinimumSize());
608 using net::test::SetFrameLength;
609 using net::test::SetFrameFlags;
610 using net::test::CompareCharArraysWithHexError;
611 using net::test::SpdyFramerTestUtil;
612 using net::test::TestSpdyVisitor;
613 using net::test::GetSerializedHeaders;
617 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
619 void SetUp() override {
620 spdy_version_ = GetParam();
621 spdy_version_ch_ = static_cast<unsigned char>(
622 SpdyConstants::SerializeMajorVersion(spdy_version_));
625 void CompareFrame(const string& description,
626 const SpdyFrame& actual_frame,
627 const unsigned char* expected,
628 const int expected_len) {
629 const unsigned char* actual =
630 reinterpret_cast<const unsigned char*>(actual_frame.data());
631 CompareCharArraysWithHexError(
632 description, actual, actual_frame.size(), expected, expected_len);
635 void CompareFrames(const string& description,
636 const SpdyFrame& expected_frame,
637 const SpdyFrame& actual_frame) {
638 CompareCharArraysWithHexError(
640 reinterpret_cast<const unsigned char*>(expected_frame.data()),
641 expected_frame.size(),
642 reinterpret_cast<const unsigned char*>(actual_frame.data()),
643 actual_frame.size());
646 // Returns true if the two header blocks have equivalent content.
647 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
648 const SpdyHeaderBlock* actual) {
649 if (expected->size() != actual->size()) {
650 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
651 << actual->size() << ".";
654 for (SpdyHeaderBlock::const_iterator it = expected->begin();
655 it != expected->end();
657 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
658 if (it2 == actual->end()) {
659 LOG(ERROR) << "Expected header name '" << it->first << "'.";
662 if (it->second.compare(it2->second) != 0) {
663 LOG(ERROR) << "Expected header named '" << it->first
664 << "' to have a value of '" << it->second
665 << "'. The actual value received was '" << it2->second
673 bool IsSpdy2() { return spdy_version_ == SPDY2; }
674 bool IsSpdy3() { return spdy_version_ == SPDY3; }
675 bool IsSpdy4() { return spdy_version_ == SPDY4; }
676 bool IsSpdy5() { return spdy_version_ == SPDY5; }
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.WriteString("name");
881 frame.WriteString("value1");
882 frame.WriteString("name");
883 frame.WriteString("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.WriteString("name");
927 frame.WriteString(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_, ElementsAre(
954 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 SettingsMap settings;
2524 settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
2525 EXPECT_EQ(kFlags, settings[kId].first);
2526 EXPECT_EQ(kValue, settings[kId].second);
2527 settings_ir.AddSetting(kId,
2528 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2529 kFlags & SETTINGS_FLAG_PERSISTED,
2532 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2534 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2535 } else if (IsSpdy3()) {
2536 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2538 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2543 const char kDescription[] = "Basic SETTINGS frame";
2545 const unsigned char kV2FrameData[] = {
2546 0x80, spdy_version_ch_, 0x00, 0x04,
2547 0x00, 0x00, 0x00, 0x24,
2548 0x00, 0x00, 0x00, 0x04,
2549 0x01, 0x00, 0x00, 0x00, // 1st Setting
2550 0x00, 0x00, 0x00, 0x05,
2551 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2552 0x00, 0x00, 0x00, 0x06,
2553 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2554 0x00, 0x00, 0x00, 0x07,
2555 0x04, 0x00, 0x00, 0x00, // 4th Setting
2556 0x00, 0x00, 0x00, 0x08,
2558 const unsigned char kV3FrameData[] = {
2559 0x80, spdy_version_ch_, 0x00, 0x04,
2560 0x00, 0x00, 0x00, 0x24,
2561 0x00, 0x00, 0x00, 0x04,
2562 0x00, 0x00, 0x00, 0x01, // 1st Setting
2563 0x00, 0x00, 0x00, 0x05,
2564 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2565 0x00, 0x00, 0x00, 0x06,
2566 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2567 0x00, 0x00, 0x00, 0x07,
2568 0x00, 0x00, 0x00, 0x04, // 4th Setting
2569 0x00, 0x00, 0x00, 0x08,
2571 // These end up seemingly out of order because of the way that our internal
2572 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2574 const unsigned char kV4FrameData[] = {
2575 0x00, 0x00, 0x18, 0x04,
2576 0x00, 0x00, 0x00, 0x00,
2577 0x00, 0x00, 0x03, // 3rd Setting
2578 0x00, 0x00, 0x00, 0x07,
2579 0x00, 0x04, // 4th Setting
2580 0x00, 0x00, 0x00, 0x08,
2581 0x00, 0x01, // 1st Setting
2582 0x00, 0x00, 0x00, 0x05,
2583 0x00, 0x02, // 2nd Setting
2584 0x00, 0x00, 0x00, 0x06,
2587 SpdySettingsIR settings_ir;
2588 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2592 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2596 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2600 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2604 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2607 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2608 } else if (IsSpdy3()) {
2609 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2611 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2616 const char kDescription[] = "Empty SETTINGS frame";
2618 const unsigned char kV3FrameData[] = { // Also applies for V2.
2619 0x80, spdy_version_ch_, 0x00, 0x04,
2620 0x00, 0x00, 0x00, 0x04,
2621 0x00, 0x00, 0x00, 0x00,
2623 const unsigned char kV4FrameData[] = {
2624 0x00, 0x00, 0x00, 0x04,
2625 0x00, 0x00, 0x00, 0x00,
2628 SpdySettingsIR settings_ir;
2629 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2631 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2633 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2638 TEST_P(SpdyFramerTest, CreatePingFrame) {
2639 SpdyFramer framer(spdy_version_);
2642 const char kDescription[] = "PING frame";
2643 const unsigned char kV3FrameData[] = { // Also applies for V2.
2644 0x80, spdy_version_ch_, 0x00, 0x06,
2645 0x00, 0x00, 0x00, 0x04,
2646 0x12, 0x34, 0x56, 0x78,
2648 const unsigned char kV4FrameData[] = {
2649 0x00, 0x00, 0x08, 0x06,
2650 0x00, 0x00, 0x00, 0x00,
2651 0x00, 0x12, 0x34, 0x56,
2652 0x78, 0x9a, 0xbc, 0xde,
2655 const unsigned char kV4FrameDataWithAck[] = {
2656 0x00, 0x00, 0x08, 0x06,
2657 0x01, 0x00, 0x00, 0x00,
2658 0x00, 0x12, 0x34, 0x56,
2659 0x78, 0x9a, 0xbc, 0xde,
2662 scoped_ptr<SpdyFrame> frame;
2664 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2665 SpdyPingIR ping_ir(kPingId);
2666 // Tests SpdyPingIR when the ping is not an ack.
2667 ASSERT_FALSE(ping_ir.is_ack());
2668 frame.reset(framer.SerializePing(ping_ir));
2669 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2671 // Tests SpdyPingIR when the ping is an ack.
2672 ping_ir.set_is_ack(true);
2673 frame.reset(framer.SerializePing(ping_ir));
2674 CompareFrame(kDescription, *frame,
2675 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2678 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2679 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2684 TEST_P(SpdyFramerTest, CreateGoAway) {
2685 SpdyFramer framer(spdy_version_);
2688 const char kDescription[] = "GOAWAY frame";
2689 const unsigned char kV2FrameData[] = {
2690 0x80, spdy_version_ch_, 0x00, 0x07,
2691 0x00, 0x00, 0x00, 0x04,
2692 0x00, 0x00, 0x00, 0x00, // Stream Id
2694 const unsigned char kV3FrameData[] = {
2695 0x80, spdy_version_ch_, 0x00, 0x07,
2696 0x00, 0x00, 0x00, 0x08,
2697 0x00, 0x00, 0x00, 0x00, // Stream Id
2698 0x00, 0x00, 0x00, 0x00, // Status
2700 const unsigned char kV4FrameData[] = {
2701 0x00, 0x00, 0x0a, 0x07,
2702 0x00, 0x00, 0x00, 0x00,
2703 0x00, 0x00, 0x00, 0x00, // Stream id
2704 0x00, 0x00, 0x00, 0x00, // Status
2705 0x00, 0x47, 0x41, // Opaque Description
2707 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2708 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2710 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2711 } else if (IsSpdy3()) {
2712 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2714 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2719 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2720 const unsigned char kV2FrameData[] = {
2721 0x80, spdy_version_ch_, 0x00, 0x07,
2722 0x00, 0x00, 0x00, 0x04,
2723 0x7f, 0xff, 0xff, 0xff, // Stream Id
2725 const unsigned char kV3FrameData[] = {
2726 0x80, spdy_version_ch_, 0x00, 0x07,
2727 0x00, 0x00, 0x00, 0x08,
2728 0x7f, 0xff, 0xff, 0xff, // Stream Id
2729 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2731 const unsigned char kV4FrameData[] = {
2732 0x00, 0x00, 0x0a, 0x07,
2733 0x00, 0x00, 0x00, 0x00,
2734 0x00, 0x7f, 0xff, 0xff, // Stream Id
2735 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2736 0x02, 0x47, 0x41, // Opaque Description
2738 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2739 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2741 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2742 } else if (IsSpdy3()) {
2743 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2745 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2750 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2751 SpdyFramer framer(spdy_version_);
2752 framer.set_enable_compression(false);
2755 const char kDescription[] = "HEADERS frame, no FIN";
2757 const unsigned char kV2FrameData[] = {
2758 0x80, spdy_version_ch_, 0x00, 0x08,
2759 0x00, 0x00, 0x00, 0x1C,
2760 0x00, 0x00, 0x00, 0x01,
2761 0x00, 0x00, 0x00, 0x02,
2762 0x00, 0x03, 'b', 'a',
2763 'r', 0x00, 0x03, 'f',
2764 'o', 'o', 0x00, 0x03,
2765 'f', 'o', 'o', 0x00,
2768 const unsigned char kV3FrameData[] = {
2769 0x80, spdy_version_ch_, 0x00, 0x08,
2770 0x00, 0x00, 0x00, 0x24,
2771 0x00, 0x00, 0x00, 0x01,
2772 0x00, 0x00, 0x00, 0x02,
2773 0x00, 0x00, 0x00, 0x03,
2774 'b', 'a', 'r', 0x00,
2775 0x00, 0x00, 0x03, 'f',
2776 'o', 'o', 0x00, 0x00,
2777 0x00, 0x03, 'f', 'o',
2778 'o', 0x00, 0x00, 0x00,
2781 const unsigned char kV4FrameData[] = {
2782 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2783 0x04, 0x00, 0x00, 0x00, // Stream 1
2784 0x01, 0x00, 0x03, 0x62, // @.ba
2785 0x61, 0x72, 0x03, 0x66, // r.fo
2786 0x6f, 0x6f, 0x00, 0x03, // o@.f
2787 0x66, 0x6f, 0x6f, 0x03, // oo.b
2788 0x62, 0x61, 0x72, // ar
2790 SpdyHeadersIR headers_ir(1);
2791 headers_ir.SetHeader("bar", "foo");
2792 headers_ir.SetHeader("foo", "bar");
2793 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2795 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2796 } else if (IsSpdy3()) {
2797 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2799 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2804 const char kDescription[] =
2805 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2807 const unsigned char kV2FrameData[] = {
2808 0x80, spdy_version_ch_, 0x00, 0x08,
2809 0x01, 0x00, 0x00, 0x19,
2810 0x7f, 0xff, 0xff, 0xff,
2811 0x00, 0x00, 0x00, 0x02,
2812 0x00, 0x00, 0x00, 0x03,
2813 'f', 'o', 'o', 0x00,
2814 0x03, 'f', 'o', 'o',
2815 0x00, 0x03, 'b', 'a',
2818 const unsigned char kV3FrameData[] = {
2819 0x80, spdy_version_ch_, 0x00, 0x08,
2820 0x01, 0x00, 0x00, 0x21,
2821 0x7f, 0xff, 0xff, 0xff,
2822 0x00, 0x00, 0x00, 0x02,
2823 0x00, 0x00, 0x00, 0x00,
2824 0x00, 0x00, 0x00, 0x03,
2825 'f', 'o', 'o', 0x00,
2826 0x00, 0x00, 0x03, 'f',
2827 'o', 'o', 0x00, 0x00,
2828 0x00, 0x03, 'b', 'a',
2831 const unsigned char kV4FrameData[] = {
2832 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2833 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2834 0xff, 0x00, 0x00, 0x03, // @..
2835 0x66, 0x6f, 0x6f, 0x00, // foo@
2836 0x03, 0x66, 0x6f, 0x6f, // .foo
2837 0x03, 0x62, 0x61, 0x72, // .bar
2839 SpdyHeadersIR headers_ir(0x7fffffff);
2840 headers_ir.set_fin(true);
2841 headers_ir.SetHeader("", "foo");
2842 headers_ir.SetHeader("foo", "bar");
2843 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2845 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2846 } else if (IsSpdy3()) {
2847 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2849 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2854 const char kDescription[] =
2855 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2857 const unsigned char kV2FrameData[] = {
2858 0x80, spdy_version_ch_, 0x00, 0x08,
2859 0x01, 0x00, 0x00, 0x19,
2860 0x7f, 0xff, 0xff, 0xff,
2861 0x00, 0x00, 0x00, 0x02,
2862 0x00, 0x03, 'b', 'a',
2863 'r', 0x00, 0x03, 'f',
2864 'o', 'o', 0x00, 0x03,
2865 'f', 'o', 'o', 0x00,
2868 const unsigned char kV3FrameData[] = {
2869 0x80, spdy_version_ch_, 0x00, 0x08,
2870 0x01, 0x00, 0x00, 0x21,
2871 0x7f, 0xff, 0xff, 0xff,
2872 0x00, 0x00, 0x00, 0x02,
2873 0x00, 0x00, 0x00, 0x03,
2874 'b', 'a', 'r', 0x00,
2875 0x00, 0x00, 0x03, 'f',
2876 'o', 'o', 0x00, 0x00,
2877 0x00, 0x03, 'f', 'o',
2878 'o', 0x00, 0x00, 0x00,
2881 const unsigned char kV4FrameData[] = {
2882 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2883 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2884 0xff, 0x00, 0x03, 0x62, // @.b
2885 0x61, 0x72, 0x03, 0x66, // ar.f
2886 0x6f, 0x6f, 0x00, 0x03, // oo@.
2887 0x66, 0x6f, 0x6f, 0x00, // foo.
2889 SpdyHeadersIR headers_ir(0x7fffffff);
2890 headers_ir.set_fin(true);
2891 headers_ir.SetHeader("bar", "foo");
2892 headers_ir.SetHeader("foo", "");
2893 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2895 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2896 } else if (IsSpdy3()) {
2897 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2899 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2904 const char kDescription[] =
2905 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2907 const unsigned char kV4FrameData[] = {
2908 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2909 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2910 0xff, 0x00, 0x00, 0x00, // parent stream
2911 0x00, 0xdb, // weight
2912 0x00, 0x03, 0x62, 0x61, // @.ba
2913 0x72, 0x03, 0x66, 0x6f, // r.fo
2914 0x6f, 0x00, 0x03, 0x66, // o@.f
2915 0x6f, 0x6f, 0x00, // oo.
2917 SpdyHeadersIR headers_ir(0x7fffffff);
2918 headers_ir.set_fin(true);
2919 headers_ir.set_priority(1);
2920 headers_ir.set_has_priority(true);
2921 headers_ir.SetHeader("bar", "foo");
2922 headers_ir.SetHeader("foo", "");
2923 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2924 if (IsSpdy2() || IsSpdy3()) {
2925 // HEADERS with priority not supported.
2927 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2932 const char kDescription[] =
2933 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2935 const unsigned char kV4FrameData[] = {
2936 0x00, 0x00, 0x15, 0x01, // Headers
2937 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2939 0xff, 0x05, 0x00, 0x00, // Pad length field
2940 0x03, 0x66, 0x6f, 0x6f, // .foo
2941 0x00, 0x03, 0x66, 0x6f, // @.fo
2942 0x6f, 0x03, 0x62, 0x61, // o.ba
2945 0x00, 0x00, 0x00, 0x00, 0x00,
2947 SpdyHeadersIR headers_ir(0x7fffffff);
2948 headers_ir.set_fin(true);
2949 headers_ir.SetHeader("", "foo");
2950 headers_ir.SetHeader("foo", "bar");
2951 headers_ir.set_padding_len(6);
2952 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2953 if (IsSpdy2() || IsSpdy3()) {
2954 // Padding is not supported.
2956 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2961 // TODO(phajdan.jr): Clean up after we no longer need
2962 // to workaround http://crbug.com/139744.
2963 #if !defined(USE_SYSTEM_ZLIB)
2964 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2965 SpdyFramer framer(spdy_version_);
2966 framer.set_enable_compression(true);
2969 const char kDescription[] = "HEADERS frame, no FIN";
2971 const unsigned char kV2FrameData[] = {
2972 0x80, spdy_version_ch_, 0x00, 0x08,
2973 0x00, 0x00, 0x00, 0x32,
2974 0x00, 0x00, 0x00, 0x01,
2975 0x00, 0x00, 0x38, 0xea,
2976 0xdf, 0xa2, 0x51, 0xb2,
2977 0x62, 0x60, 0x62, 0x60,
2978 0x4e, 0x4a, 0x2c, 0x62,
2979 0x60, 0x06, 0x08, 0xa0,
2980 0xb4, 0xfc, 0x7c, 0x80,
2981 0x00, 0x62, 0x60, 0x4e,
2982 0xcb, 0xcf, 0x67, 0x60,
2983 0x06, 0x08, 0xa0, 0xa4,
2984 0xc4, 0x22, 0x80, 0x00,
2985 0x02, 0x00, 0x00, 0x00,
2988 const unsigned char kV3FrameData[] = {
2989 0x80, spdy_version_ch_, 0x00, 0x08,
2990 0x00, 0x00, 0x00, 0x31,
2991 0x00, 0x00, 0x00, 0x01,
2992 0x38, 0xea, 0xe3, 0xc6,
2993 0xa7, 0xc2, 0x02, 0xe5,
2994 0x0e, 0x50, 0xc2, 0x4b,
2995 0x4a, 0x04, 0xe5, 0x0b,
2996 0x66, 0x80, 0x00, 0x4a,
2997 0xcb, 0xcf, 0x07, 0x08,
2998 0x20, 0x10, 0x95, 0x96,
2999 0x9f, 0x0f, 0xa2, 0x00,
3000 0x02, 0x28, 0x29, 0xb1,
3001 0x08, 0x20, 0x80, 0x00,
3002 0x00, 0x00, 0x00, 0xff,
3005 const unsigned char kV2SIMDFrameData[] = {
3006 0x80, spdy_version_ch_, 0x00, 0x08,
3007 0x00, 0x00, 0x00, 0x2f,
3008 0x00, 0x00, 0x00, 0x01,
3009 0x00, 0x00, 0x38, 0xea,
3010 0xdf, 0xa2, 0x51, 0xb2,
3011 0x62, 0x60, 0x62, 0x60,
3012 0x4e, 0x4a, 0x2c, 0x62,
3013 0x60, 0x06, 0x08, 0xa0,
3014 0xb4, 0xfc, 0x7c, 0x80,
3015 0x00, 0x62, 0x60, 0x06,
3016 0x13, 0x00, 0x01, 0x94,
3017 0x94, 0x58, 0x04, 0x10,
3018 0x40, 0x00, 0x00, 0x00,
3021 const unsigned char kV3SIMDFrameData[] = {
3022 0x80, spdy_version_ch_, 0x00, 0x08,
3023 0x00, 0x00, 0x00, 0x2c,
3024 0x00, 0x00, 0x00, 0x01,
3025 0x38, 0xea, 0xe3, 0xc6,
3026 0xa7, 0xc2, 0x02, 0xe5,
3027 0x0e, 0x50, 0xc2, 0x4b,
3028 0x4a, 0x04, 0xe5, 0x0b,
3029 0x66, 0x80, 0x00, 0x4a,
3030 0xcb, 0xcf, 0x07, 0x08,
3031 0x20, 0x24, 0x0a, 0x20,
3032 0x80, 0x92, 0x12, 0x8b,
3033 0x00, 0x02, 0x08, 0x00,
3034 0x00, 0x00, 0xff, 0xff,
3037 SpdyHeadersIR headers_ir(1);
3038 headers_ir.SetHeader("bar", "foo");
3039 headers_ir.SetHeader("foo", "bar");
3040 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3041 const unsigned char* frame_data =
3042 reinterpret_cast<const unsigned char*>(frame->data());
3044 // Try comparing with SIMD version, if that fails, do a failing check
3045 // with pretty printing against non-SIMD version
3046 if (memcmp(frame_data,
3048 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3049 CompareCharArraysWithHexError(kDescription,
3053 arraysize(kV2FrameData));
3055 } else if (IsSpdy3()) {
3056 if (memcmp(frame_data,
3058 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3059 CompareCharArraysWithHexError(kDescription,
3063 arraysize(kV3FrameData));
3066 // Deflate compression doesn't apply to HPACK.
3070 #endif // !defined(USE_SYSTEM_ZLIB)
3072 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3073 SpdyFramer framer(spdy_version_);
3076 const char kDescription[] = "WINDOW_UPDATE frame";
3077 const unsigned char kV3FrameData[] = { // Also applies for V2.
3078 0x80, spdy_version_ch_, 0x00, 0x09,
3079 0x00, 0x00, 0x00, 0x08,
3080 0x00, 0x00, 0x00, 0x01,
3081 0x00, 0x00, 0x00, 0x01,
3083 const unsigned char kV4FrameData[] = {
3084 0x00, 0x00, 0x04, 0x08,
3085 0x00, 0x00, 0x00, 0x00,
3086 0x01, 0x00, 0x00, 0x00,
3089 scoped_ptr<SpdyFrame> frame(
3090 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3092 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3094 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3099 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3100 const unsigned char kV3FrameData[] = { // Also applies for V2.
3101 0x80, spdy_version_ch_, 0x00, 0x09,
3102 0x00, 0x00, 0x00, 0x08,
3103 0x7f, 0xff, 0xff, 0xff,
3104 0x00, 0x00, 0x00, 0x01,
3106 const unsigned char kV4FrameData[] = {
3107 0x00, 0x00, 0x04, 0x08,
3108 0x00, 0x7f, 0xff, 0xff,
3109 0xff, 0x00, 0x00, 0x00,
3112 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3113 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3115 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3117 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3122 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3123 const unsigned char kV3FrameData[] = { // Also applies for V2.
3124 0x80, spdy_version_ch_, 0x00, 0x09,
3125 0x00, 0x00, 0x00, 0x08,
3126 0x00, 0x00, 0x00, 0x01,
3127 0x7f, 0xff, 0xff, 0xff,
3129 const unsigned char kV4FrameData[] = {
3130 0x00, 0x00, 0x04, 0x08,
3131 0x00, 0x00, 0x00, 0x00,
3132 0x01, 0x7f, 0xff, 0xff,
3135 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3136 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3138 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3140 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3145 TEST_P(SpdyFramerTest, SerializeBlocked) {
3146 if (spdy_version_ <= SPDY3) {
3150 SpdyFramer framer(spdy_version_);
3152 const char kDescription[] = "BLOCKED frame";
3153 const unsigned char kType = static_cast<unsigned char>(
3154 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3155 const unsigned char kFrameData[] = {
3156 0x00, 0x00, 0x00, kType, 0x00,
3157 0x00, 0x00, 0x00, 0x00,
3159 SpdyBlockedIR blocked_ir(0);
3160 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3161 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3164 TEST_P(SpdyFramerTest, CreateBlocked) {
3165 if (spdy_version_ <= SPDY3) {
3169 SpdyFramer framer(spdy_version_);
3171 const char kDescription[] = "BLOCKED frame";
3172 const SpdyStreamId kStreamId = 3;
3174 scoped_ptr<SpdySerializedFrame> frame_serialized(
3175 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3176 SpdyBlockedIR blocked_ir(kStreamId);
3177 scoped_ptr<SpdySerializedFrame> frame_created(
3178 framer.SerializeFrame(blocked_ir));
3180 CompareFrames(kDescription, *frame_serialized, *frame_created);
3183 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3184 if (spdy_version_ <= SPDY3) {
3189 // Test framing PUSH_PROMISE without padding.
3190 SpdyFramer framer(spdy_version_);
3191 framer.set_enable_compression(false);
3192 const char kDescription[] = "PUSH_PROMISE frame without padding";
3194 const unsigned char kFrameData[] = {
3195 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3196 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3197 0x2a, 0x00, 0x00, 0x00, // Stream 42
3198 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3199 0x61, 0x72, 0x03, 0x66, // ar.f
3200 0x6f, 0x6f, 0x00, 0x03, // oo@.
3201 0x66, 0x6f, 0x6f, 0x03, // foo.
3202 0x62, 0x61, 0x72, // bar
3205 SpdyPushPromiseIR push_promise(42, 57);
3206 push_promise.SetHeader("bar", "foo");
3207 push_promise.SetHeader("foo", "bar");
3208 scoped_ptr<SpdySerializedFrame> frame(
3209 framer.SerializePushPromise(push_promise));
3210 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3214 // Test framing PUSH_PROMISE with one byte of padding.
3215 SpdyFramer framer(spdy_version_);
3216 framer.set_enable_compression(false);
3217 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3219 const unsigned char kFrameData[] = {
3220 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3221 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3222 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3223 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3224 0x62, 0x61, 0x72, 0x03, // bar.
3225 0x66, 0x6f, 0x6f, 0x00, // foo@
3226 0x03, 0x66, 0x6f, 0x6f, // .foo
3227 0x03, 0x62, 0x61, 0x72, // .bar
3230 SpdyPushPromiseIR push_promise(42, 57);
3231 push_promise.set_padding_len(1);
3232 push_promise.SetHeader("bar", "foo");
3233 push_promise.SetHeader("foo", "bar");
3234 scoped_ptr<SpdySerializedFrame> frame(
3235 framer.SerializePushPromise(push_promise));
3236 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3240 // Test framing PUSH_PROMISE with 177 bytes of padding.
3241 SpdyFramer framer(spdy_version_);
3242 framer.set_enable_compression(false);
3243 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3245 const unsigned char kFrameData[] = {
3246 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3247 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3248 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3249 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3250 0x62, 0x61, 0x72, 0x03, // bar.
3251 0x66, 0x6f, 0x6f, 0x00, // foo@
3252 0x03, 0x66, 0x6f, 0x6f, // .foo
3253 0x03, 0x62, 0x61, 0x72, // .bar
3254 // Padding of 176 0x00(s).
3255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3272 SpdyPushPromiseIR push_promise(42, 57);
3273 push_promise.set_padding_len(177);
3274 push_promise.SetHeader("bar", "foo");
3275 push_promise.SetHeader("foo", "bar");
3276 scoped_ptr<SpdySerializedFrame> frame(
3277 framer.SerializePushPromise(push_promise));
3278 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3282 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3283 if (spdy_version_ <= SPDY3) {
3287 SpdyFramer framer(spdy_version_);
3288 framer.set_enable_compression(false);
3289 const char kDescription[] = "CONTINUATION frame";
3291 const unsigned char kFrameData[] = {
3292 0x00, 0x00, 0x12, 0x09, 0x00, // CONTINUATION
3293 0x00, 0x00, 0x00, 0x2a, // Stream 42
3294 0x00, 0x03, 0x62, 0x61, // @.ba
3295 0x72, 0x03, 0x66, 0x6f, // r.fo
3296 0x6f, 0x00, 0x03, 0x66, // o@.f
3297 0x6f, 0x6f, 0x03, 0x62, // oo.b
3301 SpdyContinuationIR continuation(42);
3302 continuation.SetHeader("bar", "foo");
3303 continuation.SetHeader("foo", "bar");
3304 scoped_ptr<SpdySerializedFrame> frame(
3305 framer.SerializeContinuation(continuation));
3306 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3309 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3310 if (spdy_version_ <= SPDY3) {
3315 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3316 // padding, cannot hold all the data payload, which is overflowed to the
3317 // consecutive CONTINUATION frame.
3318 SpdyFramer framer(spdy_version_);
3319 framer.set_enable_compression(false);
3320 const char kDescription[] =
3321 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3323 const unsigned char kPartialPushPromiseFrameData[] = {
3324 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3325 0x08, 0x00, 0x00, 0x00, // PADDED
3326 0x2a, 0x00, 0x00, 0x00, // Stream 42
3327 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3328 0x78, 0x78, 0x78, 0x7f, // xxx.
3329 0x81, 0x07, 0x78, 0x78, // ..xx
3330 0x78, 0x78, 0x78, 0x78, // xxxx
3331 0x78, 0x78, 0x78, 0x78, // xxxx
3332 0x78, 0x78, 0x78, 0x78, // xxxx
3333 0x78, 0x78, 0x78, 0x78, // xxxx
3334 0x78, 0x78, 0x78, 0x78, // xxxx
3335 0x78, 0x78, 0x78, 0x78, // xxxx
3336 0x78, 0x78, 0x78, 0x78, // xxxx
3337 0x78, 0x78, 0x78, 0x78, // xxxx
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
3353 const unsigned char kContinuationFrameData[] = {
3354 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3355 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3356 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3357 0x78, 0x78, 0x78, 0x78, // xxxx
3358 0x78, 0x78, 0x78, 0x78, // xxxx
3359 0x78, 0x78, 0x78, 0x78, // xxxx
3360 0x78, 0x78, 0x78, 0x78, // xxxx
3364 SpdyPushPromiseIR push_promise(42, 57);
3365 push_promise.set_padding_len(1);
3366 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3367 push_promise.SetHeader("xxx", big_value);
3368 scoped_ptr<SpdySerializedFrame> frame(
3369 framer.SerializePushPromise(push_promise));
3371 // The entire frame should look like below:
3372 // Name Length in Byte
3373 // ------------------------------------------- Begin of PUSH_PROMISE frame
3374 // PUSH_PROMISE header 9
3375 // Pad length field 1
3376 // Promised stream 4
3377 // Length field of key 2
3379 // Length field of value 3
3380 // Part of big_value 16361
3381 // ------------------------------------------- Begin of CONTINUATION frame
3382 // CONTINUATION header 9
3383 // Remaining of big_value 22
3384 // ------------------------------------------- End
3386 // Length of everything listed above except big_value.
3387 int len_non_data_payload = 31;
3389 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3392 // Partially compare the PUSH_PROMISE frame against the template.
3393 const unsigned char* frame_data =
3394 reinterpret_cast<const unsigned char*>(frame->data());
3395 CompareCharArraysWithHexError(kDescription,
3397 arraysize(kPartialPushPromiseFrameData),
3398 kPartialPushPromiseFrameData,
3399 arraysize(kPartialPushPromiseFrameData));
3401 // Compare the CONTINUATION frame against the template.
3402 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3403 CompareCharArraysWithHexError(kDescription,
3405 arraysize(kContinuationFrameData),
3406 kContinuationFrameData,
3407 arraysize(kContinuationFrameData));
3411 TEST_P(SpdyFramerTest, CreateAltSvc) {
3412 if (spdy_version_ <= SPDY3) {
3416 SpdyFramer framer(spdy_version_);
3418 const char kDescription[] = "ALTSVC frame";
3419 const unsigned char kType = static_cast<unsigned char>(
3420 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3421 const unsigned char kFrameData[] = {
3422 0x00, 0x00, 0x17, kType, 0x00,
3423 0x00, 0x00, 0x00, 0x03,
3424 0x00, 0x00, 0x00, 0x05,
3425 0x01, 0xbb, 0x00, 0x04, // Port = 443
3426 'p', 'i', 'd', '1', // Protocol-ID
3427 0x04, 'h', 'o', 's',
3431 SpdyAltSvcIR altsvc_ir(3);
3432 altsvc_ir.set_max_age(5);
3433 altsvc_ir.set_port(443);
3434 altsvc_ir.set_protocol_id("pid1");
3435 altsvc_ir.set_host("host");
3436 altsvc_ir.set_origin("origin");
3437 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3438 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3441 TEST_P(SpdyFramerTest, CreatePriority) {
3442 if (spdy_version_ <= SPDY3) {
3446 SpdyFramer framer(spdy_version_);
3448 const char kDescription[] = "PRIORITY frame";
3449 const unsigned char kType = static_cast<unsigned char>(
3450 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3451 const unsigned char kFrameData[] = {
3452 0x00, 0x00, 0x05, kType, 0x00,
3453 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3454 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3455 0x10, // Weight = 16
3457 SpdyPriorityIR priority_ir(2, 1, 16, true);
3458 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3459 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3462 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3463 if (spdy_version_ > SPDY3) {
3464 // SYN_STREAM not supported in SPDY>3
3467 SpdyFramer framer(spdy_version_);
3468 SpdySynStreamIR syn_stream(1);
3469 syn_stream.set_priority(1);
3470 syn_stream.SetHeader("aa", "vv");
3471 syn_stream.SetHeader("bb", "ww");
3472 SpdyHeaderBlock headers = syn_stream.name_value_block();
3473 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3474 EXPECT_TRUE(control_frame.get() != NULL);
3475 TestSpdyVisitor visitor(spdy_version_);
3476 visitor.use_compression_ = true;
3477 visitor.SimulateInFramer(
3478 reinterpret_cast<unsigned char*>(control_frame->data()),
3479 control_frame->size());
3480 EXPECT_EQ(1, visitor.syn_frame_count_);
3481 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3484 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3485 if (spdy_version_ > SPDY3) {
3488 SpdyFramer framer(spdy_version_);
3489 SpdySynReplyIR syn_reply(1);
3490 syn_reply.SetHeader("alpha", "beta");
3491 syn_reply.SetHeader("gamma", "delta");
3492 SpdyHeaderBlock headers = syn_reply.name_value_block();
3493 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3494 EXPECT_TRUE(control_frame.get() != NULL);
3495 TestSpdyVisitor visitor(spdy_version_);
3496 visitor.use_compression_ = true;
3497 visitor.SimulateInFramer(
3498 reinterpret_cast<unsigned char*>(control_frame->data()),
3499 control_frame->size());
3501 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3502 EXPECT_EQ(1, visitor.headers_frame_count_);
3504 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3505 EXPECT_EQ(0, visitor.headers_frame_count_);
3507 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3510 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3511 SpdyFramer framer(spdy_version_);
3512 SpdyHeadersIR headers_ir(1);
3513 headers_ir.SetHeader("alpha", "beta");
3514 headers_ir.SetHeader("gamma", "delta");
3515 SpdyHeaderBlock headers = headers_ir.name_value_block();
3516 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3517 EXPECT_TRUE(control_frame.get() != NULL);
3518 TestSpdyVisitor visitor(spdy_version_);
3519 visitor.use_compression_ = true;
3520 visitor.SimulateInFramer(
3521 reinterpret_cast<unsigned char*>(control_frame->data()),
3522 control_frame->size());
3523 EXPECT_EQ(1, visitor.headers_frame_count_);
3524 // control_frame_header_data_count_ depends on the random sequence
3525 // produced by rand(), so adding, removing or running single tests
3526 // alters this value. The best we can do is assert that it happens
3528 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3529 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3530 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3531 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3534 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3535 SpdyFramer framer(spdy_version_);
3536 SpdyHeadersIR headers_ir(1);
3537 headers_ir.set_fin(true);
3538 headers_ir.SetHeader("alpha", "beta");
3539 headers_ir.SetHeader("gamma", "delta");
3540 SpdyHeaderBlock headers = headers_ir.name_value_block();
3541 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3542 EXPECT_TRUE(control_frame.get() != NULL);
3543 TestSpdyVisitor visitor(spdy_version_);
3544 visitor.use_compression_ = true;
3545 visitor.SimulateInFramer(
3546 reinterpret_cast<unsigned char*>(control_frame->data()),
3547 control_frame->size());
3548 EXPECT_EQ(1, visitor.headers_frame_count_);
3549 // control_frame_header_data_count_ depends on the random sequence
3550 // produced by rand(), so adding, removing or running single tests
3551 // alters this value. The best we can do is assert that it happens
3553 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3554 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3555 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3556 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3559 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3560 if (spdy_version_ > SPDY3) {
3561 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3564 // First find the size of the header value in order to just reach the control
3566 SpdyFramer framer(spdy_version_);
3567 framer.set_enable_compression(false);
3568 SpdySynStreamIR syn_stream(1);
3569 syn_stream.set_priority(1);
3570 syn_stream.SetHeader("aa", "");
3571 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3572 const size_t kBigValueSize =
3573 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3575 // Create a frame at exactly that size.
3576 string big_value(kBigValueSize, 'x');
3577 syn_stream.SetHeader("aa", big_value);
3578 control_frame.reset(framer.SerializeSynStream(syn_stream));
3579 EXPECT_TRUE(control_frame.get() != NULL);
3580 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3581 control_frame->size());
3583 TestSpdyVisitor visitor(spdy_version_);
3584 visitor.SimulateInFramer(
3585 reinterpret_cast<unsigned char*>(control_frame->data()),
3586 control_frame->size());
3587 EXPECT_TRUE(visitor.header_buffer_valid_);
3588 EXPECT_EQ(0, visitor.error_count_);
3589 EXPECT_EQ(1, visitor.syn_frame_count_);
3590 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3591 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3592 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3595 // This test is disabled because Chromium is willing to accept control frames up
3596 // to the maximum size allowed by the specification, and SpdyFrameBuilder is not
3597 // capable of building larger frames.
3598 TEST_P(SpdyFramerTest, DISABLED_ControlFrameTooLarge) {
3599 if (spdy_version_ > SPDY3) {
3600 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3603 // First find the size of the header value in order to just reach the control
3605 SpdyFramer framer(spdy_version_);
3606 framer.set_enable_compression(false);
3607 SpdySynStreamIR syn_stream(1);
3608 syn_stream.SetHeader("aa", "");
3609 syn_stream.set_priority(1);
3610 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3611 const size_t kBigValueSize =
3612 SpdyConstants::GetFrameMaximumSize(spdy_version_) -
3613 control_frame->size() + 1;
3615 // Create a frame at exatly that size.
3616 string big_value(kBigValueSize, 'x');
3617 syn_stream.SetHeader("aa", big_value);
3618 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3619 // neither support that in Chromium, nor do we use the same DFATAL (see
3620 // SpdyFrameBuilder::WriteFramePrefix()).
3621 control_frame.reset(framer.SerializeSynStream(syn_stream));
3623 EXPECT_TRUE(control_frame.get() != NULL);
3624 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_) + 1,
3625 control_frame->size());
3627 TestSpdyVisitor visitor(spdy_version_);
3628 visitor.SimulateInFramer(
3629 reinterpret_cast<unsigned char*>(control_frame->data()),
3630 control_frame->size());
3631 EXPECT_FALSE(visitor.header_buffer_valid_);
3632 EXPECT_EQ(1, visitor.error_count_);
3633 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3634 visitor.framer_.error_code())
3635 << SpdyFramer::ErrorCodeToString(framer.error_code());
3636 EXPECT_EQ(0, visitor.syn_frame_count_);
3637 EXPECT_EQ(0u, visitor.header_buffer_length_);
3640 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3641 if (spdy_version_ <= SPDY3) {
3644 SpdyFramer framer(spdy_version_);
3645 framer.set_enable_compression(false);
3646 SpdyHeadersIR headers(1);
3647 headers.set_padding_len(256);
3649 // Exact payload length will change with HPACK, but this should be long
3650 // enough to cause an overflow.
3651 const size_t kBigValueSize = kControlFrameSizeLimit;
3652 string big_value(kBigValueSize, 'x');
3653 headers.SetHeader("aa", big_value);
3654 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3655 EXPECT_TRUE(control_frame.get() != NULL);
3656 EXPECT_GT(control_frame->size(),
3657 TestSpdyVisitor::sent_control_frame_max_size());
3659 TestSpdyVisitor visitor(spdy_version_);
3660 visitor.SimulateInFramer(
3661 reinterpret_cast<unsigned char*>(control_frame->data()),
3662 control_frame->size());
3663 EXPECT_TRUE(visitor.header_buffer_valid_);
3664 EXPECT_EQ(0, visitor.error_count_);
3665 EXPECT_EQ(1, visitor.headers_frame_count_);
3666 EXPECT_EQ(16, visitor.continuation_count_);
3667 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3670 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3671 if (spdy_version_ <= SPDY3) {
3674 SpdyFramer framer(spdy_version_);
3675 framer.set_enable_compression(false);
3676 SpdyPushPromiseIR push_promise(1, 2);
3677 push_promise.set_padding_len(256);
3679 // Exact payload length will change with HPACK, but this should be long
3680 // enough to cause an overflow.
3681 const size_t kBigValueSize = kControlFrameSizeLimit;
3682 string big_value(kBigValueSize, 'x');
3683 push_promise.SetHeader("aa", big_value);
3684 scoped_ptr<SpdyFrame> control_frame(
3685 framer.SerializePushPromise(push_promise));
3686 EXPECT_TRUE(control_frame.get() != NULL);
3687 EXPECT_GT(control_frame->size(),
3688 TestSpdyVisitor::sent_control_frame_max_size());
3690 TestSpdyVisitor visitor(spdy_version_);
3691 visitor.SimulateInFramer(
3692 reinterpret_cast<unsigned char*>(control_frame->data()),
3693 control_frame->size());
3694 EXPECT_TRUE(visitor.header_buffer_valid_);
3695 EXPECT_EQ(0, visitor.error_count_);
3696 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3697 EXPECT_EQ(16, visitor.continuation_count_);
3698 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3701 // Check that the framer stops delivering header data chunks once the visitor
3702 // declares it doesn't want any more. This is important to guard against
3703 // "zip bomb" types of attacks.
3704 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3705 const size_t kHeaderBufferChunks = 4;
3706 const size_t kHeaderBufferSize =
3707 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3708 const size_t kBigValueSize = kHeaderBufferSize * 2;
3709 string big_value(kBigValueSize, 'x');
3710 SpdyFramer framer(spdy_version_);
3711 SpdyHeadersIR headers(1);
3712 headers.set_priority(1);
3713 headers.set_fin(true);
3714 headers.SetHeader("aa", big_value);
3715 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3716 EXPECT_TRUE(control_frame.get() != NULL);
3717 TestSpdyVisitor visitor(spdy_version_);
3718 visitor.set_header_buffer_size(kHeaderBufferSize);
3719 visitor.use_compression_ = true;
3720 visitor.SimulateInFramer(
3721 reinterpret_cast<unsigned char*>(control_frame->data()),
3722 control_frame->size());
3723 EXPECT_FALSE(visitor.header_buffer_valid_);
3724 EXPECT_EQ(1, visitor.error_count_);
3725 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3726 visitor.framer_.error_code())
3727 << SpdyFramer::ErrorCodeToString(framer.error_code());
3729 // The framer should have stoped delivering chunks after the visitor
3730 // signaled "stop" by returning false from OnControlFrameHeaderData().
3732 // control_frame_header_data_count_ depends on the random sequence
3733 // produced by rand(), so adding, removing or running single tests
3734 // alters this value. The best we can do is assert that it happens
3735 // at least kHeaderBufferChunks + 1.
3736 EXPECT_LE(kHeaderBufferChunks + 1,
3737 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3738 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3740 // The framer should not have sent half-close to the visitor.
3741 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3744 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3745 if (spdy_version_ > SPDY3) {
3746 // Deflate compression doesn't apply to HPACK.
3749 SpdyFramer framer(spdy_version_);
3750 framer.set_enable_compression(false);
3751 // Construct a SYN_STREAM control frame without compressing the header block,
3752 // and have the framer try to decompress it. This will cause the framer to
3753 // deal with a decompression error.
3754 SpdySynStreamIR syn_stream(1);
3755 syn_stream.set_priority(1);
3756 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3757 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3758 TestSpdyVisitor visitor(spdy_version_);
3759 visitor.use_compression_ = true;
3760 visitor.SimulateInFramer(
3761 reinterpret_cast<unsigned char*>(control_frame->data()),
3762 control_frame->size());
3763 EXPECT_EQ(1, visitor.error_count_);
3764 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3765 << SpdyFramer::ErrorCodeToString(framer.error_code());
3766 EXPECT_EQ(0u, visitor.header_buffer_length_);
3769 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3770 SpdyFramer framer(spdy_version_);
3771 // Create a GoAway frame that has a few extra bytes at the end.
3772 // We create enough overhead to overflow the framer's control frame buffer.
3773 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize);
3774 const unsigned char length = 1 + SpdyFramer::kControlFrameBufferSize;
3775 const unsigned char kV3FrameData[] = { // Also applies for V2.
3776 0x80, spdy_version_ch_, 0x00, 0x07,
3777 0x00, 0x00, 0x00, length,
3778 0x00, 0x00, 0x00, 0x00, // Stream ID
3779 0x00, 0x00, 0x00, 0x00, // Status
3782 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3783 // since it may carry opaque data. Verify that minimal length is tested.
3784 const unsigned char less_than_min_length =
3785 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3786 const unsigned char kV4FrameData[] = {
3787 0x00, 0x00, static_cast<uint8>(less_than_min_length), 0x07,
3788 0x00, 0x00, 0x00, 0x00,
3789 0x00, 0x00, 0x00, 0x00, // Stream Id
3790 0x00, 0x00, 0x00, 0x00, // Status
3793 const size_t pad_length =
3794 length + framer.GetControlFrameHeaderSize() -
3795 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3796 string pad('A', pad_length);
3797 TestSpdyVisitor visitor(spdy_version_);
3800 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3802 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3804 visitor.SimulateInFramer(
3805 reinterpret_cast<const unsigned char*>(pad.c_str()),
3808 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3809 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3810 visitor.framer_.error_code())
3811 << SpdyFramer::ErrorCodeToString(framer.error_code());
3812 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3815 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3816 SpdyFramer framer(spdy_version_);
3817 SpdySettingsIR settings_ir;
3818 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3819 SetFrameLength(control_frame.get(), 0, spdy_version_);
3820 TestSpdyVisitor visitor(spdy_version_);
3821 visitor.use_compression_ = false;
3822 visitor.SimulateInFramer(
3823 reinterpret_cast<unsigned char*>(control_frame->data()),
3824 framer.GetControlFrameHeaderSize());
3825 if (spdy_version_ <= SPDY3) {
3826 // Should generate an error, since zero-len settings frames are unsupported.
3827 EXPECT_EQ(1, visitor.error_count_);
3829 // Zero-len settings frames are permitted as of SPDY 4.
3830 EXPECT_EQ(0, visitor.error_count_);
3834 // Tests handling of SETTINGS frames with invalid length.
3835 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3836 SpdyFramer framer(spdy_version_);
3837 SpdySettingsIR settings_ir;
3839 // Add a setting to pad the frame so that we don't get a buffer overflow when
3840 // calling SimulateInFramer() below.
3841 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3845 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3846 const size_t kNewLength = 14;
3847 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3848 TestSpdyVisitor visitor(spdy_version_);
3849 visitor.use_compression_ = false;
3850 visitor.SimulateInFramer(
3851 reinterpret_cast<unsigned char*>(control_frame->data()),
3852 framer.GetControlFrameHeaderSize() + kNewLength);
3853 // Should generate an error, since its not possible to have a
3854 // settings frame of length kNewLength.
3855 EXPECT_EQ(1, visitor.error_count_);
3858 // Tests handling of SETTINGS frames larger than the frame buffer size.
3859 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3860 SpdyFramer framer(spdy_version_);
3861 SpdySettingsIR settings_ir;
3862 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3866 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3870 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3875 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3876 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3877 control_frame->size());
3878 TestSpdyVisitor visitor(spdy_version_);
3879 visitor.use_compression_ = false;
3881 // Read all at once.
3882 visitor.SimulateInFramer(
3883 reinterpret_cast<unsigned char*>(control_frame->data()),
3884 control_frame->size());
3885 EXPECT_EQ(0, visitor.error_count_);
3886 EXPECT_EQ(3, visitor.setting_count_);
3887 if (spdy_version_ > SPDY3) {
3888 EXPECT_EQ(1, visitor.settings_ack_sent_);
3891 // Read data in small chunks.
3892 size_t framed_data = 0;
3893 size_t unframed_data = control_frame->size();
3894 size_t kReadChunkSize = 5; // Read five bytes at a time.
3895 while (unframed_data > 0) {
3896 size_t to_read = min(kReadChunkSize, unframed_data);
3897 visitor.SimulateInFramer(
3898 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3900 unframed_data -= to_read;
3901 framed_data += to_read;
3903 EXPECT_EQ(0, visitor.error_count_);
3904 EXPECT_EQ(3 * 2, visitor.setting_count_);
3905 if (spdy_version_ > SPDY3) {
3906 EXPECT_EQ(2, visitor.settings_ack_sent_);
3910 // Tests handling of SETTINGS frame with duplicate entries.
3911 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3912 SpdyFramer framer(spdy_version_);
3914 const unsigned char kV2FrameData[] = {
3915 0x80, spdy_version_ch_, 0x00, 0x04,
3916 0x00, 0x00, 0x00, 0x1C,
3917 0x00, 0x00, 0x00, 0x03,
3918 0x01, 0x00, 0x00, 0x00, // 1st Setting
3919 0x00, 0x00, 0x00, 0x02,
3920 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3921 0x00, 0x00, 0x00, 0x03,
3922 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3923 0x00, 0x00, 0x00, 0x03,
3925 const unsigned char kV3FrameData[] = {
3926 0x80, spdy_version_ch_, 0x00, 0x04,
3927 0x00, 0x00, 0x00, 0x1C,
3928 0x00, 0x00, 0x00, 0x03,
3929 0x00, 0x00, 0x00, 0x01, // 1st Setting
3930 0x00, 0x00, 0x00, 0x02,
3931 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3932 0x00, 0x00, 0x00, 0x03,
3933 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3934 0x00, 0x00, 0x00, 0x03,
3936 const unsigned char kV4FrameData[] = {
3937 0x00, 0x00, 0x12, 0x04,
3938 0x00, 0x00, 0x00, 0x00,
3939 0x00, 0x00, 0x01, // 1st Setting
3940 0x00, 0x00, 0x00, 0x02,
3941 0x00, 0x01, // 2nd (duplicate) Setting
3942 0x00, 0x00, 0x00, 0x03,
3943 0x00, 0x03, // 3rd (unprocessed) Setting
3944 0x00, 0x00, 0x00, 0x03,
3947 TestSpdyVisitor visitor(spdy_version_);
3948 visitor.use_compression_ = false;
3950 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3951 } else if (IsSpdy3()) {
3952 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3954 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3958 EXPECT_EQ(1, visitor.setting_count_);
3959 EXPECT_EQ(1, visitor.error_count_);
3961 // In SPDY 4+, duplicate settings are allowed;
3962 // each setting replaces the previous value for that setting.
3963 EXPECT_EQ(3, visitor.setting_count_);
3964 EXPECT_EQ(0, visitor.error_count_);
3965 EXPECT_EQ(1, visitor.settings_ack_sent_);
3969 // Tests handling of SETTINGS frame with a setting we don't recognize.
3970 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3971 SpdyFramer framer(spdy_version_);
3973 const unsigned char kV2FrameData[] = {
3974 0x80, spdy_version_ch_, 0x00, 0x04,
3975 0x00, 0x00, 0x00, 0x1C,
3976 0x00, 0x00, 0x00, 0x01,
3977 0x10, 0x00, 0x00, 0x00, // 1st Setting
3978 0x00, 0x00, 0x00, 0x02,
3980 const unsigned char kV3FrameData[] = {
3981 0x80, spdy_version_ch_, 0x00, 0x04,
3982 0x00, 0x00, 0x00, 0x1C,
3983 0x00, 0x00, 0x00, 0x01,
3984 0x00, 0x00, 0x00, 0x10, // 1st Setting
3985 0x00, 0x00, 0x00, 0x02,
3987 const unsigned char kV4FrameData[] = {
3988 0x00, 0x00, 0x06, 0x04,
3989 0x00, 0x00, 0x00, 0x00,
3990 0x00, 0x00, 0x10, // 1st Setting
3991 0x00, 0x00, 0x00, 0x02,
3994 TestSpdyVisitor visitor(spdy_version_);
3995 visitor.use_compression_ = false;
3997 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3998 } else if (IsSpdy3()) {
3999 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4001 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4005 EXPECT_EQ(0, visitor.setting_count_);
4006 EXPECT_EQ(1, visitor.error_count_);
4008 // In SPDY 4+, we ignore unknown settings because of extensions.
4009 EXPECT_EQ(0, visitor.setting_count_);
4010 EXPECT_EQ(0, visitor.error_count_);
4014 // Tests handling of SETTINGS frame with entries out of order.
4015 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
4016 SpdyFramer framer(spdy_version_);
4018 const unsigned char kV2FrameData[] = {
4019 0x80, spdy_version_ch_, 0x00, 0x04,
4020 0x00, 0x00, 0x00, 0x1C,
4021 0x00, 0x00, 0x00, 0x03,
4022 0x02, 0x00, 0x00, 0x00, // 1st Setting
4023 0x00, 0x00, 0x00, 0x02,
4024 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4025 0x00, 0x00, 0x00, 0x03,
4026 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4027 0x00, 0x00, 0x00, 0x03,
4029 const unsigned char kV3FrameData[] = {
4030 0x80, spdy_version_ch_, 0x00, 0x04,
4031 0x00, 0x00, 0x00, 0x1C,
4032 0x00, 0x00, 0x00, 0x03,
4033 0x00, 0x00, 0x00, 0x02, // 1st Setting
4034 0x00, 0x00, 0x00, 0x02,
4035 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4036 0x00, 0x00, 0x00, 0x03,
4037 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4038 0x00, 0x00, 0x00, 0x03,
4040 const unsigned char kV4FrameData[] = {
4041 0x00, 0x00, 0x12, 0x04,
4042 0x00, 0x00, 0x00, 0x00,
4043 0x00, 0x00, 0x02, // 1st Setting
4044 0x00, 0x00, 0x00, 0x02,
4045 0x00, 0x01, // 2nd (out of order) Setting
4046 0x00, 0x00, 0x00, 0x03,
4047 0x00, 0x03, // 3rd (unprocessed) Setting
4048 0x00, 0x00, 0x00, 0x03,
4051 TestSpdyVisitor visitor(spdy_version_);
4052 visitor.use_compression_ = false;
4054 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4055 } else if (IsSpdy3()) {
4056 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4058 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4062 EXPECT_EQ(1, visitor.setting_count_);
4063 EXPECT_EQ(1, visitor.error_count_);
4065 // In SPDY 4+, settings are allowed in any order.
4066 EXPECT_EQ(3, visitor.setting_count_);
4067 EXPECT_EQ(0, visitor.error_count_);
4071 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4072 if (spdy_version_ <= SPDY3) {
4075 SpdyFramer framer(spdy_version_);
4077 const unsigned char kFrameData[] = {
4078 0x00, 0x00, 0x00, 0x04, 0x01,
4079 0x00, 0x00, 0x00, 0x00,
4082 TestSpdyVisitor visitor(spdy_version_);
4083 visitor.use_compression_ = false;
4084 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4086 EXPECT_EQ(0, visitor.error_count_);
4087 EXPECT_EQ(0, visitor.setting_count_);
4088 EXPECT_EQ(1, visitor.settings_ack_received_);
4091 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4092 if (spdy_version_ <= SPDY3) {
4096 const int kPaddingLen = 119;
4097 const char data_payload[] = "hello";
4099 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4100 SpdyFramer framer(spdy_version_);
4101 framer.set_visitor(&visitor);
4103 SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
4104 data_ir.set_padding_len(kPaddingLen);
4105 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4106 ASSERT_TRUE(frame.get() != NULL);
4108 int bytes_consumed = 0;
4110 // Send the frame header.
4111 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4112 kPaddingLen + strlen(data_payload),
4114 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4115 framer.ProcessInput(frame->data(),
4116 framer.GetDataFrameMinimumSize()));
4117 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4118 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4119 bytes_consumed += framer.GetDataFrameMinimumSize();
4121 // Send the padding length field.
4122 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4123 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4124 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4125 bytes_consumed += 1;
4127 // Send the first two bytes of the data payload, i.e., "he".
4128 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4129 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4130 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4131 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4132 bytes_consumed += 2;
4134 // Send the rest three bytes of the data payload, i.e., "llo".
4135 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4136 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4137 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4138 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4139 bytes_consumed += 3;
4141 // Send the first 100 bytes of the padding payload.
4142 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false));
4143 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4144 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4145 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4146 bytes_consumed += 100;
4148 // Send rest of the padding payload.
4149 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 18, false));
4150 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4151 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
4152 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4155 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4156 SpdyFramer framer(spdy_version_);
4157 scoped_ptr<SpdyFrame> control_frame(
4158 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4159 TestSpdyVisitor visitor(spdy_version_);
4160 visitor.SimulateInFramer(
4161 reinterpret_cast<unsigned char*>(control_frame->data()),
4162 control_frame->size());
4163 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4164 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4167 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4171 SpdyFramer framer(spdy_version_);
4172 const unsigned char kV3FrameData[] = { // Also applies for V2.
4173 0x80, spdy_version_ch_, 0x00, 0x0A,
4174 0x00, 0x00, 0x00, 0x33,
4175 0x00, 0x03, 0x00, 0x00,
4176 0x00, 0x05, 'p', 'r',
4177 'o', 'o', 'f', 0x00,
4178 0x00, 0x00, 0x06, 'a',
4180 't', 0x00, 0x00, 0x00,
4181 0x0C, 'a', 'n', 'o',
4184 't', 0x00, 0x00, 0x00,
4185 0x0A, 'f', 'i', 'n',
4189 TestSpdyVisitor visitor(spdy_version_);
4190 visitor.use_compression_ = false;
4191 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4192 EXPECT_EQ(0, visitor.error_count_);
4195 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4199 SpdyFramer framer(spdy_version_);
4200 const unsigned char kV3FrameData[] = { // Also applies for V2.
4201 0x80, spdy_version_ch_, 0x00, 0x0A,
4202 0x00, 0x00, 0x00, 0x33,
4203 0x00, 0x03, 0x00, 0x00,
4204 0x00, 0x05, 'p', 'r',
4205 'o', 'o', 'f', 0x00,
4206 0x00, 0x00, 0x06, 'a',
4208 't', 0x00, 0x00, 0x00,
4209 0x0C, 'a', 'n', 'o',
4212 't', 0x00, 0x00, 0x00,
4213 0x0A, 'f', 'i', 'n',
4217 TestSpdyVisitor visitor(spdy_version_);
4218 visitor.use_compression_ = false;
4219 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4220 arraysize(kV3FrameData));
4221 scoped_ptr<SpdyFrame> control_frame(
4222 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4223 multiple_frame_data.append(string(control_frame->data(),
4224 control_frame->size()));
4225 visitor.SimulateInFramer(
4226 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4227 multiple_frame_data.length());
4228 EXPECT_EQ(0, visitor.error_count_);
4229 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4230 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4233 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4234 if (spdy_version_ <= SPDY3) {
4238 SpdyFramer framer(spdy_version_);
4239 SpdyPushPromiseIR push_promise(42, 57);
4240 push_promise.SetHeader("foo", "bar");
4241 push_promise.SetHeader("bar", "foofoo");
4242 SpdyHeaderBlock headers = push_promise.name_value_block();
4243 scoped_ptr<SpdySerializedFrame> frame(
4244 framer.SerializePushPromise(push_promise));
4245 EXPECT_TRUE(frame.get() != NULL);
4246 TestSpdyVisitor visitor(spdy_version_);
4247 visitor.use_compression_ = true;
4248 visitor.SimulateInFramer(
4249 reinterpret_cast<unsigned char*>(frame->data()),
4251 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4252 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4253 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4256 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4257 if (spdy_version_ <= SPDY3) {
4261 const unsigned char kInput[] = {
4262 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4263 0x00, 0x00, 0x00, 0x01, // Stream 1
4264 0x03, // Padding of 3.
4265 0x00, 0x06, 0x63, 0x6f,
4266 0x6f, 0x6b, 0x69, 0x65,
4267 0x07, 0x66, 0x6f, 0x6f,
4268 0x3d, 0x62, 0x61, 0x72,
4271 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4272 0x00, 0x00, 0x00, 0x01, // Stream 1
4273 0x00, 0x06, 0x63, 0x6f,
4274 0x6f, 0x6b, 0x69, 0x65,
4275 0x08, 0x62, 0x61, 0x7a,
4276 0x3d, 0x62, 0x69, 0x6e,
4277 0x67, 0x00, 0x06, 0x63,
4279 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4280 0x00, 0x00, 0x00, 0x01, // Stream 1
4281 0x6f, 0x6f, 0x6b, 0x69,
4282 0x65, 0x00, 0x00, 0x04,
4283 0x6e, 0x61, 0x6d, 0x65,
4284 0x05, 0x76, 0x61, 0x6c,
4288 TestSpdyVisitor visitor(spdy_version_);
4289 visitor.SimulateInFramer(kInput, sizeof(kInput));
4291 EXPECT_EQ(0, visitor.error_count_);
4292 EXPECT_EQ(1, visitor.headers_frame_count_);
4293 EXPECT_EQ(2, visitor.continuation_count_);
4294 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4295 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4297 EXPECT_THAT(visitor.headers_, ElementsAre(
4298 Pair("cookie", "foo=bar; baz=bing; "),
4299 Pair("name", "value")));
4302 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4303 if (spdy_version_ <= SPDY3) {
4307 const unsigned char kInput[] = {
4308 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4309 0x00, 0x00, 0x00, 0x01, // Stream 1
4310 0x00, 0x06, 0x63, 0x6f,
4311 0x6f, 0x6b, 0x69, 0x65,
4312 0x07, 0x66, 0x6f, 0x6f,
4313 0x3d, 0x62, 0x61, 0x72,
4315 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4316 0x00, 0x00, 0x00, 0x01, // Stream 1
4317 0x00, 0x06, 0x63, 0x6f,
4318 0x6f, 0x6b, 0x69, 0x65,
4319 0x08, 0x62, 0x61, 0x7a,
4320 0x3d, 0x62, 0x69, 0x6e,
4321 0x67, 0x00, 0x06, 0x63,
4323 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4324 0x00, 0x00, 0x00, 0x01, // Stream 1
4325 0x6f, 0x6f, 0x6b, 0x69,
4326 0x65, 0x00, 0x00, 0x04,
4327 0x6e, 0x61, 0x6d, 0x65,
4328 0x05, 0x76, 0x61, 0x6c,
4332 SpdyFramer framer(spdy_version_);
4333 TestSpdyVisitor visitor(spdy_version_);
4334 visitor.SimulateInFramer(kInput, sizeof(kInput));
4336 EXPECT_EQ(0, visitor.error_count_);
4337 EXPECT_EQ(1, visitor.headers_frame_count_);
4338 EXPECT_EQ(2, visitor.continuation_count_);
4339 EXPECT_EQ(1, visitor.fin_flag_count_);
4340 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4341 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4343 EXPECT_THAT(visitor.headers_, ElementsAre(
4344 Pair("cookie", "foo=bar; baz=bing; "),
4345 Pair("name", "value")));
4348 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4349 if (spdy_version_ <= SPDY3) {
4353 const unsigned char kInput[] = {
4354 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4355 0x08, 0x00, 0x00, 0x00, // PADDED
4356 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4357 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4358 0x63, 0x6f, 0x6f, 0x6b,
4359 0x69, 0x65, 0x07, 0x66,
4360 0x6f, 0x6f, 0x3d, 0x62,
4361 0x61, 0x72, 0x00, 0x00,
4363 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4364 0x00, 0x00, 0x00, 0x00,
4365 0x01, 0x00, 0x06, 0x63, // Stream 1
4366 0x6f, 0x6f, 0x6b, 0x69,
4367 0x65, 0x08, 0x62, 0x61,
4368 0x7a, 0x3d, 0x62, 0x69,
4369 0x6e, 0x67, 0x00, 0x06,
4372 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4373 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4374 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4375 0x69, 0x65, 0x00, 0x00,
4376 0x04, 0x6e, 0x61, 0x6d,
4377 0x65, 0x05, 0x76, 0x61,
4381 SpdyFramer framer(spdy_version_);
4382 TestSpdyVisitor visitor(spdy_version_);
4383 visitor.SimulateInFramer(kInput, sizeof(kInput));
4385 EXPECT_EQ(0, visitor.error_count_);
4386 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4387 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4388 EXPECT_EQ(2, visitor.continuation_count_);
4389 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4390 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4392 EXPECT_THAT(visitor.headers_, ElementsAre(
4393 Pair("cookie", "foo=bar; baz=bing; "),
4394 Pair("name", "value")));
4397 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4398 if (spdy_version_ <= SPDY3) {
4402 const unsigned char kInput[] = {
4403 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4404 0x00, 0x00, 0x00, 0x01, // Stream 1
4405 0x00, 0x06, 0x63, 0x6f,
4406 0x6f, 0x6b, 0x69, 0x65,
4407 0x07, 0x66, 0x6f, 0x6f,
4408 0x3d, 0x62, 0x61, 0x72,
4410 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4411 0x00, 0x00, 0x00, 0x02, // Stream 2
4412 0x00, 0x06, 0x63, 0x6f,
4413 0x6f, 0x6b, 0x69, 0x65,
4414 0x08, 0x62, 0x61, 0x7a,
4415 0x3d, 0x62, 0x69, 0x6e,
4416 0x67, 0x00, 0x06, 0x63,
4419 SpdyFramer framer(spdy_version_);
4420 TestSpdyVisitor visitor(spdy_version_);
4421 framer.set_visitor(&visitor);
4422 visitor.SimulateInFramer(kInput, sizeof(kInput));
4424 EXPECT_EQ(1, visitor.error_count_);
4425 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4426 visitor.framer_.error_code())
4427 << SpdyFramer::ErrorCodeToString(framer.error_code());
4428 EXPECT_EQ(1, visitor.headers_frame_count_);
4429 EXPECT_EQ(0, visitor.continuation_count_);
4430 EXPECT_EQ(0u, visitor.header_buffer_length_);
4433 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4434 if (spdy_version_ <= SPDY3) {
4438 const unsigned char kInput[] = {
4439 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4440 0x00, 0x00, 0x00, 0x01, // Stream 1
4441 0x00, 0x06, 0x63, 0x6f,
4442 0x6f, 0x6b, 0x69, 0x65,
4443 0x07, 0x66, 0x6f, 0x6f,
4444 0x3d, 0x62, 0x61, 0x72,
4447 SpdyFramer framer(spdy_version_);
4448 TestSpdyVisitor visitor(spdy_version_);
4449 framer.set_visitor(&visitor);
4450 visitor.SimulateInFramer(kInput, sizeof(kInput));
4452 EXPECT_EQ(1, visitor.error_count_);
4453 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4454 visitor.framer_.error_code())
4455 << SpdyFramer::ErrorCodeToString(framer.error_code());
4456 EXPECT_EQ(0, visitor.continuation_count_);
4457 EXPECT_EQ(0u, visitor.header_buffer_length_);
4460 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4461 if (spdy_version_ <= SPDY3) {
4465 const unsigned char kInput[] = {
4466 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4467 0x00, 0x00, 0x00, 0x01, // Stream 1
4468 0x00, 0x06, 0x63, 0x6f,
4469 0x6f, 0x6b, 0x69, 0x65,
4470 0x07, 0x66, 0x6f, 0x6f,
4471 0x3d, 0x62, 0x61, 0x72,
4473 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4474 0x00, 0x00, 0x00, 0x04,
4475 0xde, 0xad, 0xbe, 0xef,
4478 SpdyFramer framer(spdy_version_);
4479 TestSpdyVisitor visitor(spdy_version_);
4480 framer.set_visitor(&visitor);
4481 visitor.SimulateInFramer(kInput, sizeof(kInput));
4483 EXPECT_EQ(1, visitor.error_count_);
4484 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4485 visitor.framer_.error_code())
4486 << SpdyFramer::ErrorCodeToString(framer.error_code());
4487 EXPECT_EQ(1, visitor.headers_frame_count_);
4488 EXPECT_EQ(0, visitor.continuation_count_);
4489 EXPECT_EQ(0u, visitor.header_buffer_length_);
4490 EXPECT_EQ(0, visitor.data_frame_count_);
4493 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4494 if (spdy_version_ <= SPDY3) {
4498 const unsigned char kInput[] = {
4499 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4500 0x00, 0x00, 0x00, 0x01, // Stream 1
4501 0x00, 0x06, 0x63, 0x6f,
4502 0x6f, 0x6b, 0x69, 0x65,
4503 0x07, 0x66, 0x6f, 0x6f,
4504 0x3d, 0x62, 0x61, 0x72,
4506 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4507 0x00, 0x00, 0x00, 0x01, // Stream 1
4508 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4509 0x6f, 0x6b, 0x69, 0x65,
4510 0x08, 0x62, 0x61, 0x7a,
4511 0x3d, 0x62, 0x69, 0x6e,
4512 0x67, 0x00, 0x06, 0x63,
4515 SpdyFramer framer(spdy_version_);
4516 TestSpdyVisitor visitor(spdy_version_);
4517 framer.set_visitor(&visitor);
4518 visitor.SimulateInFramer(kInput, sizeof(kInput));
4520 EXPECT_EQ(1, visitor.error_count_);
4521 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4522 visitor.framer_.error_code())
4523 << SpdyFramer::ErrorCodeToString(framer.error_code());
4524 EXPECT_EQ(1, visitor.headers_frame_count_);
4525 EXPECT_EQ(0, visitor.continuation_count_);
4526 EXPECT_EQ(0u, visitor.header_buffer_length_);
4527 EXPECT_EQ(0, visitor.data_frame_count_);
4530 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4531 if (spdy_version_ <= SPDY3) {
4534 const unsigned char kInput[] = {
4535 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4536 0x00, 0x00, 0x00, 0x01, // Stream 1
4537 0xde, 0xad, 0xbe, 0xef,
4538 0xde, 0xad, 0xbe, 0xef,
4539 0xde, 0xad, 0xbe, 0xef,
4542 TestSpdyVisitor visitor(spdy_version_);
4543 visitor.SimulateInFramer(kInput, sizeof(kInput));
4545 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4546 EXPECT_EQ(0, visitor.error_count_);
4547 EXPECT_EQ(12, visitor.data_bytes_);
4548 EXPECT_EQ(0, visitor.fin_frame_count_);
4549 EXPECT_EQ(0, visitor.fin_flag_count_);
4552 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4553 if (spdy_version_ <= SPDY3) {
4556 const unsigned char kInput[] = {
4557 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4558 0x00, 0x00, 0x00, 0x01, // Stream 1
4559 0x00, 0x06, 0x63, 0x6f,
4560 0x6f, 0x6b, 0x69, 0x65,
4561 0x07, 0x66, 0x6f, 0x6f,
4562 0x3d, 0x62, 0x61, 0x72,
4565 TestSpdyVisitor visitor(spdy_version_);
4566 visitor.SimulateInFramer(kInput, sizeof(kInput));
4568 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4569 EXPECT_EQ(0, visitor.error_count_);
4570 EXPECT_EQ(1, visitor.headers_frame_count_);
4571 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4573 EXPECT_THAT(visitor.headers_, ElementsAre(
4574 Pair("cookie", "foo=bar")));
4577 TEST_P(SpdyFramerTest, ReadGarbage) {
4578 SpdyFramer framer(spdy_version_);
4579 unsigned char garbage_frame[256];
4580 memset(garbage_frame, ~0, sizeof(garbage_frame));
4581 TestSpdyVisitor visitor(spdy_version_);
4582 visitor.use_compression_ = false;
4583 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4584 EXPECT_EQ(1, visitor.error_count_);
4587 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4588 if (spdy_version_ <= SPDY3) {
4591 SpdyFramer framer(spdy_version_);
4593 // The unrecognized frame type should still have a valid length.
4594 const unsigned char unknown_frame[] = {
4595 0x00, 0x00, 0x08, 0xff, 0xff,
4596 0xff, 0xff, 0xff, 0xff,
4597 0xff, 0xff, 0xff, 0xff,
4598 0xff, 0xff, 0xff, 0xff,
4600 TestSpdyVisitor visitor(spdy_version_);
4602 // Simulate the case where the stream id validation checks out.
4603 visitor.on_unknown_frame_result_ = true;
4604 visitor.use_compression_ = false;
4605 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4606 EXPECT_EQ(0, visitor.error_count_);
4608 // Follow it up with a valid control frame to make sure we handle
4609 // subsequent frames correctly.
4610 SpdySettingsIR settings_ir;
4611 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4615 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4616 visitor.SimulateInFramer(
4617 reinterpret_cast<unsigned char*>(control_frame->data()),
4618 control_frame->size());
4619 EXPECT_EQ(0, visitor.error_count_);
4620 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4621 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4624 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4628 SpdyFramer framer(spdy_version_);
4629 const unsigned char kFrameData[] = {
4630 0x00, 0x00, 0x08, 0xff, 0xff,
4631 0xff, 0xff, 0xff, 0xff,
4632 0xff, 0xff, 0xff, 0xff,
4633 0xff, 0xff, 0xff, 0xff,
4635 TestSpdyVisitor visitor(spdy_version_);
4636 visitor.use_compression_ = false;
4637 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4638 EXPECT_EQ(1, visitor.error_count_);
4641 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4643 // Not valid for SPDY 4 since there is no version field.
4646 SpdyFramer framer(spdy_version_);
4647 const unsigned char kFrameData[] = {
4648 0x80, spdy_version_ch_, 0xff, 0xff,
4649 0xff, 0xff, 0xff, 0xff,
4651 TestSpdyVisitor visitor(spdy_version_);
4652 visitor.use_compression_ = false;
4653 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4654 EXPECT_EQ(1, visitor.error_count_);
4657 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4658 if (spdy_version_ <= SPDY3) {
4661 const unsigned char kInput[] = {
4662 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4663 0x00, 0x00, 0x00, 0x01, // Stream 1
4664 0xef, 0xef, 0xff, 0xff,
4665 0xff, 0xff, 0xff, 0xff,
4666 0xff, 0xff, 0xff, 0xff,
4667 0xff, 0xff, 0xff, 0xff,
4671 TestSpdyVisitor visitor(spdy_version_);
4672 visitor.SimulateInFramer(kInput, arraysize(kInput));
4673 EXPECT_EQ(1, visitor.error_count_);
4676 TEST_P(SpdyFramerTest, SizesTest) {
4677 SpdyFramer framer(spdy_version_);
4678 if (IsSpdy4() || IsSpdy5()) {
4679 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4680 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4681 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4682 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4683 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4684 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4685 EXPECT_EQ(17u, framer.GetPingSize());
4686 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4687 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4688 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4689 EXPECT_EQ(9u, framer.GetBlockedSize());
4690 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4691 EXPECT_EQ(18u, framer.GetAltSvcMinimumSize());
4692 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4693 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4694 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4696 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4697 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4698 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4699 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4700 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4701 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4702 EXPECT_EQ(12u, framer.GetPingSize());
4703 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4704 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4705 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4706 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4707 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4708 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4712 TEST_P(SpdyFramerTest, StateToStringTest) {
4713 EXPECT_STREQ("ERROR",
4714 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4715 EXPECT_STREQ("AUTO_RESET",
4716 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4717 EXPECT_STREQ("RESET",
4718 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4719 EXPECT_STREQ("READING_COMMON_HEADER",
4720 SpdyFramer::StateToString(
4721 SpdyFramer::SPDY_READING_COMMON_HEADER));
4722 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4723 SpdyFramer::StateToString(
4724 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4725 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4726 SpdyFramer::StateToString(
4727 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4728 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4729 SpdyFramer::StateToString(
4730 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4731 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4732 SpdyFramer::StateToString(
4733 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4734 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4735 SpdyFramer::StateToString(
4736 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4737 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4738 SpdyFramer::StateToString(
4739 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4740 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4741 SpdyFramer::StateToString(
4742 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4743 EXPECT_STREQ("UNKNOWN_STATE",
4744 SpdyFramer::StateToString(
4745 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4748 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4749 EXPECT_STREQ("NO_ERROR",
4750 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4751 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4752 SpdyFramer::ErrorCodeToString(
4753 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4754 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4755 SpdyFramer::ErrorCodeToString(
4756 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4757 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4758 SpdyFramer::ErrorCodeToString(
4759 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4760 EXPECT_STREQ("UNSUPPORTED_VERSION",
4761 SpdyFramer::ErrorCodeToString(
4762 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4763 EXPECT_STREQ("DECOMPRESS_FAILURE",
4764 SpdyFramer::ErrorCodeToString(
4765 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4766 EXPECT_STREQ("COMPRESS_FAILURE",
4767 SpdyFramer::ErrorCodeToString(
4768 SpdyFramer::SPDY_COMPRESS_FAILURE));
4769 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4770 SpdyFramer::ErrorCodeToString(
4771 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4772 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4773 SpdyFramer::ErrorCodeToString(
4774 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4775 EXPECT_STREQ("UNKNOWN_ERROR",
4776 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4779 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4780 EXPECT_STREQ("INVALID",
4781 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4782 EXPECT_STREQ("PROTOCOL_ERROR",
4783 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4784 EXPECT_STREQ("INVALID_STREAM",
4785 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4786 EXPECT_STREQ("REFUSED_STREAM",
4787 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4788 EXPECT_STREQ("UNSUPPORTED_VERSION",
4789 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4790 EXPECT_STREQ("CANCEL",
4791 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4792 EXPECT_STREQ("INTERNAL_ERROR",
4793 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4794 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4795 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4796 EXPECT_STREQ("UNKNOWN_STATUS",
4797 SpdyFramer::StatusCodeToString(-1));
4800 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4801 EXPECT_STREQ("DATA",
4802 SpdyFramer::FrameTypeToString(DATA));
4803 EXPECT_STREQ("SYN_STREAM",
4804 SpdyFramer::FrameTypeToString(SYN_STREAM));
4805 EXPECT_STREQ("SYN_REPLY",
4806 SpdyFramer::FrameTypeToString(SYN_REPLY));
4807 EXPECT_STREQ("RST_STREAM",
4808 SpdyFramer::FrameTypeToString(RST_STREAM));
4809 EXPECT_STREQ("SETTINGS",
4810 SpdyFramer::FrameTypeToString(SETTINGS));
4811 EXPECT_STREQ("PING",
4812 SpdyFramer::FrameTypeToString(PING));
4813 EXPECT_STREQ("GOAWAY",
4814 SpdyFramer::FrameTypeToString(GOAWAY));
4815 EXPECT_STREQ("HEADERS",
4816 SpdyFramer::FrameTypeToString(HEADERS));
4817 EXPECT_STREQ("WINDOW_UPDATE",
4818 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4819 EXPECT_STREQ("PUSH_PROMISE",
4820 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4821 EXPECT_STREQ("CREDENTIAL",
4822 SpdyFramer::FrameTypeToString(CREDENTIAL));
4823 EXPECT_STREQ("CONTINUATION",
4824 SpdyFramer::FrameTypeToString(CONTINUATION));
4827 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4829 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4833 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4834 SpdyFramer framer(spdy_version_);
4835 framer.set_visitor(&visitor);
4837 EXPECT_CALL(visitor, OnError(_));
4838 framer.ProcessInput("HTTP/1.1", 8);
4839 EXPECT_TRUE(framer.probable_http_response());
4840 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4841 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4842 << SpdyFramer::ErrorCodeToString(framer.error_code());
4845 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4846 SpdyFramer framer(spdy_version_);
4847 framer.set_visitor(&visitor);
4849 EXPECT_CALL(visitor, OnError(_));
4850 framer.ProcessInput("HTTP/1.0", 8);
4851 EXPECT_TRUE(framer.probable_http_response());
4852 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4853 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4854 << SpdyFramer::ErrorCodeToString(framer.error_code());
4858 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4859 if (spdy_version_ > SPDY3) {
4863 for (int flags = 0; flags < 256; ++flags) {
4864 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4866 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4867 SpdyFramer framer(spdy_version_);
4868 framer.set_visitor(&visitor);
4870 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4871 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4872 SetFrameFlags(frame.get(), flags, spdy_version_);
4874 if (flags & ~DATA_FLAG_FIN) {
4875 EXPECT_CALL(visitor, OnError(_));
4877 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4878 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4879 if (flags & DATA_FLAG_FIN) {
4880 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4884 framer.ProcessInput(frame->data(), frame->size());
4885 if (flags & ~DATA_FLAG_FIN) {
4886 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4887 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4888 framer.error_code())
4889 << SpdyFramer::ErrorCodeToString(framer.error_code());
4891 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4892 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4893 << SpdyFramer::ErrorCodeToString(framer.error_code());
4898 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4899 if (spdy_version_ <= SPDY3) {
4903 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4906 for (int flags = 0; flags < 256; ++flags) {
4907 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4909 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4910 SpdyFramer framer(spdy_version_);
4911 framer.set_visitor(&visitor);
4913 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4914 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4915 SetFrameFlags(frame.get(), flags, spdy_version_);
4917 if (flags & ~valid_data_flags) {
4918 EXPECT_CALL(visitor, OnError(_));
4920 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4921 if (flags & DATA_FLAG_PADDED) {
4922 // Expect Error since we don't set padded in payload.
4923 EXPECT_CALL(visitor, OnError(_));
4925 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4926 if (flags & DATA_FLAG_FIN) {
4927 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4932 framer.ProcessInput(frame->data(), frame->size());
4933 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
4934 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4935 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4936 framer.error_code())
4937 << SpdyFramer::ErrorCodeToString(framer.error_code());
4939 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4940 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4941 << SpdyFramer::ErrorCodeToString(framer.error_code());
4946 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4947 if (!IsSpdy2() && !IsSpdy3()) {
4948 // SYN_STREAM not supported in SPDY>3
4951 for (int flags = 0; flags < 256; ++flags) {
4952 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4954 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4955 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4956 SpdyFramer framer(spdy_version_);
4957 framer.set_visitor(&visitor);
4958 framer.set_debug_visitor(&debug_visitor);
4960 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4962 SpdySynStreamIR syn_stream(8);
4963 syn_stream.set_associated_to_stream_id(3);
4964 syn_stream.set_priority(1);
4965 syn_stream.SetHeader("foo", "bar");
4966 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4967 int set_flags = flags;
4968 SetFrameFlags(frame.get(), set_flags, spdy_version_);
4970 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4971 EXPECT_CALL(visitor, OnError(_));
4973 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
4974 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
4975 flags & CONTROL_FLAG_UNIDIRECTIONAL));
4976 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
4977 .WillRepeatedly(testing::Return(true));
4978 if (flags & DATA_FLAG_FIN) {
4979 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4981 // Do not close the stream if we are expecting a CONTINUATION frame.
4982 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4986 framer.ProcessInput(frame->data(), frame->size());
4987 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4988 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4989 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4990 framer.error_code())
4991 << SpdyFramer::ErrorCodeToString(framer.error_code());
4993 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4994 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4995 << SpdyFramer::ErrorCodeToString(framer.error_code());
5000 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
5001 if (!IsSpdy2() && !IsSpdy3()) {
5002 // SYN_REPLY not supported in SPDY>3
5005 for (int flags = 0; flags < 256; ++flags) {
5006 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5008 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5009 SpdyFramer framer(spdy_version_);
5010 framer.set_visitor(&visitor);
5012 SpdySynReplyIR syn_reply(37);
5013 syn_reply.SetHeader("foo", "bar");
5014 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5015 SetFrameFlags(frame.get(), flags, spdy_version_);
5017 if (flags & ~CONTROL_FLAG_FIN) {
5018 EXPECT_CALL(visitor, OnError(_));
5020 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5021 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5022 .WillRepeatedly(testing::Return(true));
5023 if (flags & DATA_FLAG_FIN) {
5024 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5028 framer.ProcessInput(frame->data(), frame->size());
5029 if (flags & ~CONTROL_FLAG_FIN) {
5030 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5031 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5032 framer.error_code())
5033 << SpdyFramer::ErrorCodeToString(framer.error_code());
5035 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5036 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5037 << SpdyFramer::ErrorCodeToString(framer.error_code());
5042 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5043 for (int flags = 0; flags < 256; ++flags) {
5044 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5046 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5047 SpdyFramer framer(spdy_version_);
5048 framer.set_visitor(&visitor);
5050 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5051 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5052 SetFrameFlags(frame.get(), flags, spdy_version_);
5055 EXPECT_CALL(visitor, OnError(_));
5057 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5060 framer.ProcessInput(frame->data(), frame->size());
5062 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5063 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5064 framer.error_code())
5065 << SpdyFramer::ErrorCodeToString(framer.error_code());
5067 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5068 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5069 << SpdyFramer::ErrorCodeToString(framer.error_code());
5074 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5075 if (spdy_version_ > SPDY3) { return; }
5076 for (int flags = 0; flags < 256; ++flags) {
5077 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5079 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5080 SpdyFramer framer(spdy_version_);
5081 framer.set_visitor(&visitor);
5083 SpdySettingsIR settings_ir;
5084 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5088 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5089 SetFrameFlags(frame.get(), flags, spdy_version_);
5091 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5092 EXPECT_CALL(visitor, OnError(_));
5094 EXPECT_CALL(visitor, OnSettings(
5095 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5096 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5097 SETTINGS_FLAG_NONE, 54321));
5098 EXPECT_CALL(visitor, OnSettingsEnd());
5101 framer.ProcessInput(frame->data(), frame->size());
5102 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5103 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5104 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5105 framer.error_code())
5106 << SpdyFramer::ErrorCodeToString(framer.error_code());
5108 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5109 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5110 << SpdyFramer::ErrorCodeToString(framer.error_code());
5115 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5116 if (spdy_version_ <= SPDY3) { return; }
5117 for (int flags = 0; flags < 256; ++flags) {
5118 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5120 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5121 SpdyFramer framer(spdy_version_);
5122 framer.set_visitor(&visitor);
5124 SpdySettingsIR settings_ir;
5125 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5126 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5127 SetFrameFlags(frame.get(), flags, spdy_version_);
5130 EXPECT_CALL(visitor, OnError(_));
5132 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5133 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5134 EXPECT_CALL(visitor, OnSettingsEnd());
5137 framer.ProcessInput(frame->data(), frame->size());
5138 if (flags & ~SETTINGS_FLAG_ACK) {
5139 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5140 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5141 framer.error_code())
5142 << SpdyFramer::ErrorCodeToString(framer.error_code());
5143 } else if (flags & SETTINGS_FLAG_ACK) {
5144 // The frame is invalid because ACK frames should have no payload.
5145 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5146 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5147 framer.error_code())
5148 << SpdyFramer::ErrorCodeToString(framer.error_code());
5150 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5151 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5152 << SpdyFramer::ErrorCodeToString(framer.error_code());
5157 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5158 for (int flags = 0; flags < 256; ++flags) {
5159 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5161 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5162 SpdyFramer framer(spdy_version_);
5163 framer.set_visitor(&visitor);
5165 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5166 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5167 SetFrameFlags(frame.get(), flags, spdy_version_);
5170 EXPECT_CALL(visitor, OnError(_));
5172 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5175 framer.ProcessInput(frame->data(), frame->size());
5177 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5178 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5179 framer.error_code())
5180 << SpdyFramer::ErrorCodeToString(framer.error_code());
5182 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5183 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5184 << SpdyFramer::ErrorCodeToString(framer.error_code());
5189 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5190 for (int flags = 0; flags < 256; ++flags) {
5191 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5193 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5194 SpdyFramer framer(spdy_version_);
5195 framer.set_visitor(&visitor);
5197 SpdyHeadersIR headers_ir(57);
5198 if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
5199 headers_ir.set_priority(3);
5200 headers_ir.set_has_priority(true);
5202 headers_ir.SetHeader("foo", "bar");
5203 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5204 int set_flags = flags;
5206 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5207 // and implement framing.
5208 set_flags &= ~HEADERS_FLAG_PADDED;
5210 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5212 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5213 EXPECT_CALL(visitor, OnError(_));
5214 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5215 HEADERS_FLAG_END_HEADERS |
5216 HEADERS_FLAG_END_SEGMENT |
5217 HEADERS_FLAG_PADDED |
5218 HEADERS_FLAG_PRIORITY)) {
5219 EXPECT_CALL(visitor, OnError(_));
5221 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5222 EXPECT_CALL(visitor, OnHeaders(57, // stream id
5223 true, // has priority?
5225 flags & CONTROL_FLAG_FIN, // fin?
5226 (flags & HEADERS_FLAG_END_HEADERS) ||
5227 !IsSpdy4())); // end headers?
5229 EXPECT_CALL(visitor, OnHeaders(57, false, 0,
5230 flags & CONTROL_FLAG_FIN,
5231 (flags & HEADERS_FLAG_END_HEADERS) ||
5234 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5235 .WillRepeatedly(testing::Return(true));
5236 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
5237 flags & HEADERS_FLAG_END_HEADERS)) {
5238 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5240 // Do not close the stream if we are expecting a CONTINUATION frame.
5241 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5245 framer.ProcessInput(frame->data(), frame->size());
5246 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5247 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5248 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5249 framer.error_code())
5250 << SpdyFramer::ErrorCodeToString(framer.error_code());
5251 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5252 HEADERS_FLAG_END_HEADERS |
5253 HEADERS_FLAG_END_SEGMENT |
5254 HEADERS_FLAG_PADDED |
5255 HEADERS_FLAG_PRIORITY)) {
5256 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5257 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5258 framer.error_code())
5259 << SpdyFramer::ErrorCodeToString(framer.error_code());
5260 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5261 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5262 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5263 << SpdyFramer::ErrorCodeToString(framer.error_code());
5265 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5266 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5267 << SpdyFramer::ErrorCodeToString(framer.error_code());
5272 TEST_P(SpdyFramerTest, PingFrameFlags) {
5273 for (int flags = 0; flags < 256; ++flags) {
5274 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5276 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5277 SpdyFramer framer(spdy_version_);
5278 framer.set_visitor(&visitor);
5280 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5281 SetFrameFlags(frame.get(), flags, spdy_version_);
5283 if (spdy_version_ > SPDY3 &&
5284 flags == PING_FLAG_ACK) {
5285 EXPECT_CALL(visitor, OnPing(42, true));
5286 } else if (flags == 0) {
5287 EXPECT_CALL(visitor, OnPing(42, false));
5289 EXPECT_CALL(visitor, OnError(_));
5292 framer.ProcessInput(frame->data(), frame->size());
5293 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5295 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5296 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5297 << SpdyFramer::ErrorCodeToString(framer.error_code());
5299 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5300 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5301 framer.error_code())
5302 << SpdyFramer::ErrorCodeToString(framer.error_code());
5307 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5308 for (int flags = 0; flags < 256; ++flags) {
5309 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5311 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5312 SpdyFramer framer(spdy_version_);
5313 framer.set_visitor(&visitor);
5315 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5316 SpdyWindowUpdateIR(4, 1024)));
5317 SetFrameFlags(frame.get(), flags, spdy_version_);
5320 EXPECT_CALL(visitor, OnError(_));
5322 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5325 framer.ProcessInput(frame->data(), frame->size());
5327 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5328 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5329 framer.error_code())
5330 << SpdyFramer::ErrorCodeToString(framer.error_code());
5332 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5333 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5334 << SpdyFramer::ErrorCodeToString(framer.error_code());
5339 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5340 if (spdy_version_ <= SPDY3) {
5344 for (int flags = 0; flags < 256; ++flags) {
5345 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5347 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
5348 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5349 SpdyFramer framer(spdy_version_);
5350 framer.set_visitor(&visitor);
5351 framer.set_debug_visitor(&debug_visitor);
5353 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5355 SpdyPushPromiseIR push_promise(42, 57);
5356 push_promise.SetHeader("foo", "bar");
5357 scoped_ptr<SpdySerializedFrame> frame(
5358 framer.SerializePushPromise(push_promise));
5359 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5360 // and implement framing.
5361 int set_flags = flags & ~HEADERS_FLAG_PADDED;
5362 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5364 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5365 EXPECT_CALL(visitor, OnError(_));
5367 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5368 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5369 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5370 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5371 .WillRepeatedly(testing::Return(true));
5374 framer.ProcessInput(frame->data(), frame->size());
5375 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5376 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5377 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5378 framer.error_code())
5379 << SpdyFramer::ErrorCodeToString(framer.error_code());
5381 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5382 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5383 << SpdyFramer::ErrorCodeToString(framer.error_code());
5388 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5389 if (spdy_version_ <= SPDY3) {
5393 for (int flags = 0; flags < 256; ++flags) {
5394 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5396 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5397 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5398 SpdyFramer framer(spdy_version_);
5399 framer.set_visitor(&visitor);
5400 framer.set_debug_visitor(&debug_visitor);
5402 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5403 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5404 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false));
5405 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5406 .WillRepeatedly(testing::Return(true));
5408 SpdyHeadersIR headers_ir(42);
5409 headers_ir.SetHeader("foo", "bar");
5410 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5411 SetFrameFlags(frame0.get(), 0, spdy_version_);
5413 SpdyContinuationIR continuation(42);
5414 continuation.SetHeader("foo", "bar");
5415 scoped_ptr<SpdySerializedFrame> frame(
5416 framer.SerializeContinuation(continuation));
5417 SetFrameFlags(frame.get(), flags, spdy_version_);
5419 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5420 EXPECT_CALL(visitor, OnError(_));
5422 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5423 EXPECT_CALL(visitor, OnContinuation(42,
5424 flags & HEADERS_FLAG_END_HEADERS));
5425 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5426 .WillRepeatedly(testing::Return(true));
5429 framer.ProcessInput(frame0->data(), frame0->size());
5430 framer.ProcessInput(frame->data(), frame->size());
5431 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5432 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5433 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5434 framer.error_code())
5435 << SpdyFramer::ErrorCodeToString(framer.error_code());
5437 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5438 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5439 << SpdyFramer::ErrorCodeToString(framer.error_code());
5444 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5446 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5448 TEST_P(SpdyFramerTest, EmptySynStream) {
5449 if (!IsSpdy2() && !IsSpdy3()) {
5450 // SYN_STREAM not supported in SPDY>3.
5453 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5454 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5455 SpdyFramer framer(spdy_version_);
5456 framer.set_visitor(&visitor);
5457 framer.set_debug_visitor(&debug_visitor);
5459 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5461 SpdySynStreamIR syn_stream(1);
5462 syn_stream.set_priority(1);
5463 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5464 // Adjust size to remove the name/value block.
5467 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5470 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5471 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5472 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5474 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5475 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5476 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5477 << SpdyFramer::ErrorCodeToString(framer.error_code());
5480 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5481 const uint32 kId = 0x020304;
5482 const uint32 kFlags = 0x01;
5483 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5485 SettingsFlagsAndId id_and_flags =
5486 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5487 EXPECT_EQ(kId, id_and_flags.id());
5488 EXPECT_EQ(kFlags, id_and_flags.flags());
5489 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5492 // Test handling of a RST_STREAM with out-of-bounds status codes.
5493 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5494 const unsigned char kRstStreamStatusTooLow = 0x00;
5495 const unsigned char kRstStreamStatusTooHigh = 0xff;
5496 const unsigned char kV3RstStreamInvalid[] = {
5497 0x80, spdy_version_ch_, 0x00, 0x03,
5498 0x00, 0x00, 0x00, 0x08,
5499 0x00, 0x00, 0x00, 0x01,
5500 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5502 const unsigned char kV4RstStreamInvalid[] = {
5503 0x00, 0x00, 0x04, 0x03,
5504 0x00, 0x00, 0x00, 0x00,
5505 0x01, 0x00, 0x00, 0x00,
5506 kRstStreamStatusTooLow
5509 const unsigned char kV3RstStreamNumStatusCodes[] = {
5510 0x80, spdy_version_ch_, 0x00, 0x03,
5511 0x00, 0x00, 0x00, 0x08,
5512 0x00, 0x00, 0x00, 0x01,
5513 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5515 const unsigned char kV4RstStreamNumStatusCodes[] = {
5516 0x00, 0x00, 0x04, 0x03,
5517 0x00, 0x00, 0x00, 0x00,
5518 0x01, 0x00, 0x00, 0x00,
5519 kRstStreamStatusTooHigh
5522 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5523 SpdyFramer framer(spdy_version_);
5524 framer.set_visitor(&visitor);
5527 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5528 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
5529 arraysize(kV4RstStreamInvalid));
5531 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5532 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5533 arraysize(kV3RstStreamInvalid));
5535 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5536 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5537 << SpdyFramer::ErrorCodeToString(framer.error_code());
5543 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5544 framer.ProcessInput(
5545 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
5546 arraysize(kV4RstStreamNumStatusCodes));
5548 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5549 framer.ProcessInput(
5550 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5551 arraysize(kV3RstStreamNumStatusCodes));
5553 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5554 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5555 << SpdyFramer::ErrorCodeToString(framer.error_code());
5558 // Test handling of GOAWAY frames with out-of-bounds status code.
5559 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5560 if (spdy_version_ <= SPDY2) {
5563 SpdyFramer framer(spdy_version_);
5565 const unsigned char kV3FrameData[] = {
5566 0x80, spdy_version_ch_, 0x00, 0x07,
5567 0x00, 0x00, 0x00, 0x08,
5568 0x00, 0x00, 0x00, 0x01, // Stream Id
5569 0xff, 0xff, 0xff, 0xff, // Status
5571 const unsigned char kV4FrameData[] = {
5572 0x00, 0x00, 0x0a, 0x07,
5573 0x00, 0x00, 0x00, 0x00,
5574 0x00, 0x00, 0x00, 0x00, // Stream id
5575 0x01, 0xff, 0xff, 0xff, // Status
5576 0xff, 0x47, 0x41, // Opaque Description
5578 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5579 framer.set_visitor(&visitor);
5582 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5583 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5584 arraysize(kV3FrameData));
5586 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5587 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5588 arraysize(kV4FrameData));
5590 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5591 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5592 << SpdyFramer::ErrorCodeToString(framer.error_code());
5595 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5596 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5597 const unsigned char kV2FrameData[] = {
5598 0x80, spdy_version_ch_, 0x00, 0x07,
5599 0x00, 0x00, 0x00, 0x04,
5600 0xff, 0xff, 0xff, 0xff,
5602 const unsigned char kV3FrameData[] = {
5603 0x80, spdy_version_ch_, 0x00, 0x07,
5604 0x00, 0x00, 0x00, 0x08,
5605 0xff, 0xff, 0xff, 0xff,
5606 0x00, 0x00, 0x00, 0x00,
5608 const unsigned char kV4FrameData[] = {
5609 0x00, 0x00, 0x08, 0x07,
5610 0x00, 0x00, 0x00, 0x00,
5611 0x00, 0xff, 0xff, 0xff,
5612 0xff, 0x00, 0x00, 0x00,
5616 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5617 SpdyFramer framer(spdy_version_);
5618 framer.set_visitor(&visitor);
5620 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5622 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5623 arraysize(kV2FrameData));
5624 } else if (IsSpdy3()) {
5625 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5626 arraysize(kV3FrameData));
5628 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5629 arraysize(kV4FrameData));
5631 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5632 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5633 << SpdyFramer::ErrorCodeToString(framer.error_code());
5636 TEST_P(SpdyFramerTest, OnBlocked) {
5637 if (spdy_version_ <= SPDY3) {
5641 const SpdyStreamId kStreamId = 0;
5643 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5644 SpdyFramer framer(spdy_version_);
5645 framer.set_visitor(&visitor);
5647 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5649 SpdyBlockedIR blocked_ir(0);
5650 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5651 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5653 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5654 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5655 << SpdyFramer::ErrorCodeToString(framer.error_code());
5658 TEST_P(SpdyFramerTest, OnAltSvc) {
5659 if (spdy_version_ <= SPDY3) {
5663 const SpdyStreamId kStreamId = 1;
5665 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5666 SpdyFramer framer(spdy_version_);
5667 framer.set_visitor(&visitor);
5669 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5674 StringPiece("o1")));
5676 SpdyAltSvcIR altsvc_ir(1);
5677 altsvc_ir.set_max_age(10);
5678 altsvc_ir.set_port(443);
5679 altsvc_ir.set_protocol_id("pid");
5680 altsvc_ir.set_host("h1");
5681 altsvc_ir.set_origin("o1");
5682 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5683 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5684 altsvc_ir.protocol_id().length() +
5685 altsvc_ir.host().length() +
5686 altsvc_ir.origin().length());
5688 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5689 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5690 << SpdyFramer::ErrorCodeToString(framer.error_code());
5693 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5694 if (spdy_version_ <= SPDY3) {
5698 const SpdyStreamId kStreamId = 1;
5700 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5701 SpdyFramer framer(spdy_version_);
5702 framer.set_visitor(&visitor);
5704 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5711 SpdyAltSvcIR altsvc_ir(1);
5712 altsvc_ir.set_max_age(10);
5713 altsvc_ir.set_port(443);
5714 altsvc_ir.set_protocol_id("pid");
5715 altsvc_ir.set_host("h1");
5716 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5717 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5718 altsvc_ir.protocol_id().length() +
5719 altsvc_ir.host().length());
5721 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5722 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5723 << SpdyFramer::ErrorCodeToString(framer.error_code());
5726 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5727 if (spdy_version_ <= SPDY3) {
5731 const unsigned char kType = static_cast<unsigned char>(
5732 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
5734 TestSpdyVisitor visitor(spdy_version_);
5735 SpdyFramer framer(spdy_version_);
5736 framer.set_visitor(&visitor);
5738 const unsigned char kFrameDataLargePIDLen[] = {
5739 0x00, 0x00, 0x17, kType, 0x00,
5740 0x00, 0x00, 0x00, 0x03,
5741 0x00, 0x00, 0x00, 0x05,
5742 0x01, 0xbb, 0x00, 0x05, // Port = 443
5743 'p', 'i', 'd', '1', // Protocol-ID
5744 0x04, 'h', 'o', 's',
5749 visitor.SimulateInFramer(kFrameDataLargePIDLen,
5750 sizeof(kFrameDataLargePIDLen));
5751 EXPECT_EQ(1, visitor.error_count_);
5752 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5753 visitor.framer_.error_code());
5757 TestSpdyVisitor visitor(spdy_version_);
5758 SpdyFramer framer(spdy_version_);
5759 framer.set_visitor(&visitor);
5760 const unsigned char kFrameDataPIDLenLargerThanFrame[] = {
5761 0x00, 0x00, 0x17, kType, 0x00,
5762 0x00, 0x00, 0x00, 0x03,
5763 0x00, 0x00, 0x00, 0x05,
5764 0x01, 0xbb, 0x00, 0x99, // Port = 443
5765 'p', 'i', 'd', '1', // Protocol-ID
5766 0x04, 'h', 'o', 's',
5771 visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame,
5772 sizeof(kFrameDataPIDLenLargerThanFrame));
5773 EXPECT_EQ(1, visitor.error_count_);
5774 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5775 visitor.framer_.error_code());
5779 TestSpdyVisitor visitor(spdy_version_);
5780 SpdyFramer framer(spdy_version_);
5781 framer.set_visitor(&visitor);
5783 const unsigned char kFrameDataLargeHostLen[] = {
5784 0x00, 0x00, 0x17, kType, 0x00,
5785 0x00, 0x00, 0x00, 0x03,
5786 0x00, 0x00, 0x00, 0x05,
5787 0x01, 0xbb, 0x00, 0x04, // Port = 443
5788 'p', 'i', 'd', '1', // Protocol-ID
5789 0x0f, 'h', 'o', 's',
5794 visitor.SimulateInFramer(kFrameDataLargeHostLen,
5795 sizeof(kFrameDataLargeHostLen));
5796 EXPECT_EQ(1, visitor.error_count_);
5797 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5798 visitor.framer_.error_code());
5802 TestSpdyVisitor visitor(spdy_version_);
5803 SpdyFramer framer(spdy_version_);
5804 framer.set_visitor(&visitor);
5805 const unsigned char kFrameDataSmallPIDLen[] = {
5806 0x00, 0x00, 0x17, kType, 0x00,
5807 0x00, 0x00, 0x00, 0x03,
5808 0x00, 0x00, 0x00, 0x05,
5809 0x01, 0xbb, 0x00, 0x01, // Port = 443
5810 'p', 'i', 'd', '1', // Protocol-ID
5811 0x04, 'h', 'o', 's',
5816 visitor.SimulateInFramer(kFrameDataSmallPIDLen,
5817 sizeof(kFrameDataSmallPIDLen));
5818 EXPECT_EQ(1, visitor.error_count_);
5819 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5820 visitor.framer_.error_code());
5824 // Tests handling of ALTSVC frames delivered in small chunks.
5825 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5826 if (spdy_version_ <= SPDY3) {
5829 SpdyFramer framer(spdy_version_);
5830 SpdyAltSvcIR altsvc_ir(1);
5831 altsvc_ir.set_max_age(20);
5832 altsvc_ir.set_port(443);
5833 altsvc_ir.set_protocol_id("protocolid");
5834 altsvc_ir.set_host("hostname");
5836 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5837 TestSpdyVisitor visitor(spdy_version_);
5838 visitor.use_compression_ = false;
5840 // Read data in small chunks.
5841 size_t framed_data = 0;
5842 size_t unframed_data = control_frame->size();
5843 size_t kReadChunkSize = 5; // Read five bytes at a time.
5844 while (unframed_data > 0) {
5845 size_t to_read = min(kReadChunkSize, unframed_data);
5846 visitor.SimulateInFramer(
5847 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5849 unframed_data -= to_read;
5850 framed_data += to_read;
5852 EXPECT_EQ(0, visitor.error_count_);
5853 EXPECT_EQ(1, visitor.altsvc_count_);
5854 EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
5855 EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
5856 EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
5857 EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
5860 // Tests handling of PRIORITY frames.
5861 TEST_P(SpdyFramerTest, ReadPriority) {
5862 if (spdy_version_ <= SPDY3) {
5865 SpdyFramer framer(spdy_version_);
5866 SpdyPriorityIR priority(3, 1, 255, false);
5867 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5868 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5869 framer.set_visitor(&visitor);
5870 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5871 framer.ProcessInput(frame->data(), frame->size());
5873 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5874 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5875 << SpdyFramer::ErrorCodeToString(framer.error_code());
5876 // TODO(mlavan): once we actually maintain a priority tree,
5877 // check that state is adjusted correctly.
5880 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5881 if (spdy_version_ <= SPDY3) {
5884 SpdyFramer framer(spdy_version_);
5886 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5887 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5888 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5889 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5890 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5891 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5892 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5893 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5895 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5896 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5897 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5898 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5899 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5900 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5901 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5902 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5903 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5904 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5905 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5906 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5907 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5908 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5909 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5912 // Tests handling of PRIORITY frame with incorrect size.
5913 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5914 if (spdy_version_ <= SPDY3) {
5918 // PRIORITY frame of size 4, which isn't correct.
5919 const unsigned char kFrameData[] = {
5920 0x00, 0x00, 0x04, 0x02, 0x00,
5921 0x00, 0x00, 0x00, 0x03,
5922 0x00, 0x00, 0x00, 0x01,
5925 TestSpdyVisitor visitor(spdy_version_);
5926 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
5928 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
5929 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5930 visitor.framer_.error_code())
5931 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());