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/mock_spdy_framer_visitor.h"
12 #include "net/spdy/spdy_frame_builder.h"
13 #include "net/spdy/spdy_framer.h"
14 #include "net/spdy/spdy_protocol.h"
15 #include "net/spdy/spdy_test_utils.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/platform_test.h"
19 using base::StringPiece;
23 using std::numeric_limits;
30 static const size_t kMaxDecompressedSize = 1024;
32 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
34 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
39 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
44 class SpdyFramerTestUtil {
46 // Decompress a single frame using the decompression context held by
47 // the SpdyFramer. The implemention is meant for use only in tests
48 // and will CHECK fail if the input is anything other than a single,
49 // well-formed compressed frame.
51 // Returns a new decompressed SpdyFrame.
52 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
53 SpdyFramer* framer, const SpdyFrameType& frame) {
54 DecompressionVisitor visitor(framer->protocol_version());
55 framer->set_visitor(&visitor);
56 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
57 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
58 framer->set_visitor(NULL);
60 char* buffer = visitor.ReleaseBuffer();
61 CHECK(buffer != NULL);
62 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
63 if (framer->protocol_version() == 4) {
64 SetFrameLength(decompressed_frame,
66 framer->protocol_version());
68 SetFrameLength(decompressed_frame,
69 visitor.size() - framer->GetControlFrameHeaderSize(),
70 framer->protocol_version());
72 return decompressed_frame;
75 class DecompressionVisitor : public SpdyFramerVisitorInterface {
77 explicit DecompressionVisitor(SpdyMajorVersion version)
78 : version_(version), size_(0), finished_(false) {}
81 CHECK(buffer_.get() == NULL);
84 buffer_.reset(new char[kMaxDecompressedSize]);
87 virtual void OnError(SpdyFramer* framer) OVERRIDE { LOG(FATAL); }
88 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
91 LOG(FATAL) << "Unexpected data frame header";
93 virtual void OnStreamFrameData(SpdyStreamId stream_id,
100 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
101 const char* header_data,
102 size_t len) OVERRIDE {
103 CHECK(buffer_.get() != NULL);
104 CHECK_GE(kMaxDecompressedSize, size_ + len);
107 memcpy(buffer_.get() + size_, header_data, len);
116 virtual void OnSynStream(SpdyStreamId stream_id,
117 SpdyStreamId associated_stream_id,
118 SpdyPriority priority,
121 bool unidirectional) OVERRIDE {
122 SpdyFramer framer(version_);
123 framer.set_enable_compression(false);
124 SpdySynStreamIR syn_stream(stream_id);
125 syn_stream.set_associated_to_stream_id(associated_stream_id);
126 syn_stream.set_priority(priority);
127 syn_stream.set_slot(slot);
128 syn_stream.set_fin(fin);
129 syn_stream.set_unidirectional(unidirectional);
130 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
132 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
133 size_ += framer.GetSynStreamMinimumSize();
136 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
137 SpdyFramer framer(version_);
138 framer.set_enable_compression(false);
139 SpdyHeadersIR headers(stream_id);
140 headers.set_fin(fin);
141 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
143 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
144 size_ += framer.GetSynStreamMinimumSize();
147 virtual void OnRstStream(SpdyStreamId stream_id,
148 SpdyRstStreamStatus status) OVERRIDE {
151 virtual void OnSetting(SpdySettingsIds id,
153 uint32 value) OVERRIDE {
156 virtual void OnPing(uint32 unique_id) OVERRIDE {
159 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
160 SpdyGoAwayStatus status) OVERRIDE {
164 virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE {
165 SpdyFramer framer(version_);
166 framer.set_enable_compression(false);
167 SpdyHeadersIR headers(stream_id);
168 headers.set_fin(fin);
169 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
171 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
172 size_ += framer.GetHeadersMinimumSize();
175 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
179 virtual void OnPushPromise(SpdyStreamId stream_id,
180 SpdyStreamId promised_stream_id) OVERRIDE {
181 SpdyFramer framer(version_);
182 framer.set_enable_compression(false);
183 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
184 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
186 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
187 size_ += framer.GetPushPromiseMinimumSize();
190 char* ReleaseBuffer() {
192 return buffer_.release();
195 virtual void OnWindowUpdate(SpdyStreamId stream_id,
196 uint32 delta_window_size) OVERRIDE {
200 size_t size() const {
206 SpdyMajorVersion version_;
207 scoped_ptr<char[]> buffer_;
211 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
215 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
218 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
219 public SpdyFramerDebugVisitorInterface {
221 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
223 explicit TestSpdyVisitor(SpdyMajorVersion version)
225 use_compression_(false),
228 syn_reply_frame_count_(0),
229 headers_frame_count_(0),
232 last_window_update_stream_(0),
233 last_window_update_delta_(0),
234 last_push_promise_stream_(0),
235 last_push_promise_promised_stream_(0),
240 zero_length_data_frame_count_(0),
241 control_frame_header_data_count_(0),
242 zero_length_control_frame_header_data_count_(0),
243 data_frame_count_(0),
244 last_payload_len_(0),
246 header_buffer_(new char[kDefaultHeaderBufferSize]),
247 header_buffer_length_(0),
248 header_buffer_size_(kDefaultHeaderBufferSize),
249 header_stream_id_(-1),
250 header_control_type_(DATA),
251 header_buffer_valid_(false) {
254 virtual void OnError(SpdyFramer* f) OVERRIDE {
255 LOG(INFO) << "SpdyFramer Error: "
256 << SpdyFramer::ErrorCodeToString(f->error_code());
260 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
264 header_stream_id_ = stream_id;
267 virtual void OnStreamFrameData(SpdyStreamId stream_id,
271 EXPECT_EQ(header_stream_id_, stream_id);
273 ++zero_length_data_frame_count_;
276 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
278 for (size_t i = 0 ; i < len; ++i) {
279 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
282 std::cerr << "\", " << len << ")\n";
285 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
286 const char* header_data,
287 size_t len) OVERRIDE {
288 ++control_frame_header_data_count_;
289 CHECK_EQ(header_stream_id_, stream_id);
291 ++zero_length_control_frame_header_data_count_;
292 // Indicates end-of-header-block.
293 CHECK(header_buffer_valid_);
294 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
295 header_buffer_.get(), header_buffer_length_, &headers_);
296 DCHECK_EQ(header_buffer_length_, parsed_length);
299 const size_t available = header_buffer_size_ - header_buffer_length_;
300 if (len > available) {
301 header_buffer_valid_ = false;
304 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
305 header_buffer_length_ += len;
309 virtual void OnSynStream(SpdyStreamId stream_id,
310 SpdyStreamId associated_stream_id,
311 SpdyPriority priority,
312 uint8 credential_slot,
314 bool unidirectional) OVERRIDE {
316 InitHeaderStreaming(SYN_STREAM, stream_id);
322 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
323 syn_reply_frame_count_++;
324 InitHeaderStreaming(SYN_REPLY, stream_id);
330 virtual void OnRstStream(SpdyStreamId stream_id,
331 SpdyRstStreamStatus status) OVERRIDE {
335 virtual bool OnRstStreamFrameData(const char* rst_stream_data,
336 size_t len) OVERRIDE {
337 if ((rst_stream_data != NULL) && (len > 0)) {
338 fin_opaque_data_ += std::string(rst_stream_data, len);
343 virtual void OnSetting(SpdySettingsIds id,
345 uint32 value) OVERRIDE {
349 virtual void OnPing(uint32 unique_id) OVERRIDE {
353 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
354 SpdyGoAwayStatus status) OVERRIDE {
358 virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE {
359 headers_frame_count_++;
360 InitHeaderStreaming(HEADERS, stream_id);
366 virtual void OnWindowUpdate(SpdyStreamId stream_id,
367 uint32 delta_window_size) OVERRIDE {
368 last_window_update_stream_ = stream_id;
369 last_window_update_delta_ = delta_window_size;
372 virtual void OnPushPromise(SpdyStreamId stream_id,
373 SpdyStreamId promised_stream_id) OVERRIDE {
374 InitHeaderStreaming(PUSH_PROMISE, stream_id);
375 last_push_promise_stream_ = stream_id;
376 last_push_promise_promised_stream_ = promised_stream_id;
379 virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
382 size_t frame_len) OVERRIDE {
383 last_payload_len_ = payload_len;
384 last_frame_len_ = frame_len;
387 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
389 size_t frame_len) OVERRIDE {
390 last_frame_len_ = frame_len;
393 // Convenience function which runs a framer simulation with particular input.
394 void SimulateInFramer(const unsigned char* input, size_t size) {
395 framer_.set_enable_compression(use_compression_);
396 framer_.set_visitor(this);
397 size_t input_remaining = size;
398 const char* input_ptr = reinterpret_cast<const char*>(input);
399 while (input_remaining > 0 &&
400 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
401 // To make the tests more interesting, we feed random (amd small) chunks
402 // into the framer. This simulates getting strange-sized reads from
404 const size_t kMaxReadSize = 32;
406 (rand() % min(input_remaining, kMaxReadSize)) + 1;
407 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
408 input_remaining -= bytes_processed;
409 input_ptr += bytes_processed;
413 void InitHeaderStreaming(SpdyFrameType header_control_type,
414 SpdyStreamId stream_id) {
415 DCHECK_GE(header_control_type, FIRST_CONTROL_TYPE);
416 DCHECK_LE(header_control_type, LAST_CONTROL_TYPE);
417 memset(header_buffer_.get(), 0, header_buffer_size_);
418 header_buffer_length_ = 0;
419 header_stream_id_ = stream_id;
420 header_control_type_ = header_control_type;
421 header_buffer_valid_ = true;
422 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
425 // Override the default buffer size (16K). Call before using the framer!
426 void set_header_buffer_size(size_t header_buffer_size) {
427 header_buffer_size_ = header_buffer_size;
428 header_buffer_.reset(new char[header_buffer_size]);
431 static size_t header_data_chunk_max_size() {
432 return SpdyFramer::kHeaderDataChunkMaxSize;
436 bool use_compression_;
438 // Counters from the visitor callbacks.
440 int syn_frame_count_;
441 int syn_reply_frame_count_;
442 int headers_frame_count_;
445 SpdyStreamId last_window_update_stream_;
446 uint32 last_window_update_delta_;
447 SpdyStreamId last_push_promise_stream_;
448 SpdyStreamId last_push_promise_promised_stream_;
450 int fin_frame_count_; // The count of RST_STREAM type frames received.
451 std::string fin_opaque_data_;
452 int fin_flag_count_; // The count of frames with the FIN flag set.
453 int zero_length_data_frame_count_; // The count of zero-length data frames.
454 int control_frame_header_data_count_; // The count of chunks received.
455 // The count of zero-length control frame header data chunks received.
456 int zero_length_control_frame_header_data_count_;
457 int data_frame_count_;
458 size_t last_payload_len_;
459 size_t last_frame_len_;
461 // Header block streaming state:
462 scoped_ptr<char[]> header_buffer_;
463 size_t header_buffer_length_;
464 size_t header_buffer_size_;
465 SpdyStreamId header_stream_id_;
466 SpdyFrameType header_control_type_;
467 bool header_buffer_valid_;
468 SpdyHeaderBlock headers_;
471 // Retrieves serialized headers from SYN_STREAM frame.
472 // Does not check that the given frame is a SYN_STREAM.
473 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
474 const SpdyFramer& framer) {
475 return base::StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
476 frame->size() - framer.GetSynStreamMinimumSize());
483 using net::test::SetFrameLength;
484 using net::test::SetFrameFlags;
485 using net::test::CompareCharArraysWithHexError;
486 using net::test::SpdyFramerTestUtil;
487 using net::test::TestSpdyVisitor;
488 using net::test::GetSerializedHeaders;
492 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
494 virtual void SetUp() {
495 spdy_version_ = GetParam();
496 spdy_version_ch_ = static_cast<unsigned char>(spdy_version_);
499 void CompareFrame(const string& description,
500 const SpdyFrame& actual_frame,
501 const unsigned char* expected,
502 const int expected_len) {
503 const unsigned char* actual =
504 reinterpret_cast<const unsigned char*>(actual_frame.data());
505 CompareCharArraysWithHexError(
506 description, actual, actual_frame.size(), expected, expected_len);
509 void CompareFrames(const string& description,
510 const SpdyFrame& expected_frame,
511 const SpdyFrame& actual_frame) {
512 CompareCharArraysWithHexError(
514 reinterpret_cast<const unsigned char*>(expected_frame.data()),
515 expected_frame.size(),
516 reinterpret_cast<const unsigned char*>(actual_frame.data()),
517 actual_frame.size());
520 // Returns true if the two header blocks have equivalent content.
521 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
522 const SpdyHeaderBlock* actual) {
523 if (expected->size() != actual->size()) {
524 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
525 << actual->size() << ".";
528 for (SpdyHeaderBlock::const_iterator it = expected->begin();
529 it != expected->end();
531 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
532 if (it2 == actual->end()) {
533 LOG(ERROR) << "Expected header name '" << it->first << "'.";
536 if (it->second.compare(it2->second) != 0) {
537 LOG(ERROR) << "Expected header named '" << it->first
538 << "' to have a value of '" << it->second
539 << "'. The actual value received was '" << it2->second
547 void AddSpdySettingFromWireFormat(SettingsMap* settings,
550 SettingsFlagsAndId flags_and_id =
551 SettingsFlagsAndId::FromWireFormat(spdy_version_, key);
552 SpdySettingsIds id = static_cast<SpdySettingsIds>(flags_and_id.id());
553 SpdySettingsFlags flags =
554 static_cast<SpdySettingsFlags>(flags_and_id.flags());
555 CHECK(settings->find(id) == settings->end());
556 settings->insert(std::make_pair(id, SettingsFlagsAndValue(flags, value)));
559 bool IsSpdy2() { return spdy_version_ == SPDY2; }
560 bool IsSpdy3() { return spdy_version_ == SPDY3; }
561 bool IsSpdy4() { return spdy_version_ == SPDY4; }
563 // Version of SPDY protocol to be used.
564 SpdyMajorVersion spdy_version_;
565 unsigned char spdy_version_ch_;
568 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
569 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
571 ::testing::Values(SPDY2, SPDY3, SPDY4));
573 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
574 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
575 SpdyFramer framer(spdy_version_);
576 framer.set_enable_compression(false);
578 // Encode the header block into a SynStream frame.
579 SpdySynStreamIR syn_stream(1);
580 syn_stream.set_priority(1);
581 syn_stream.SetHeader("alpha", "beta");
582 syn_stream.SetHeader("gamma", "charlie");
583 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
584 EXPECT_TRUE(frame.get() != NULL);
585 base::StringPiece serialized_headers =
586 GetSerializedHeaders(frame.get(), framer);
587 SpdyHeaderBlock new_headers;
588 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
589 serialized_headers.size(),
592 SpdyHeaderBlock headers = syn_stream.name_value_block();
593 EXPECT_EQ(headers.size(), new_headers.size());
594 EXPECT_EQ(headers["alpha"], new_headers["alpha"]);
595 EXPECT_EQ(headers["gamma"], new_headers["gamma"]);
598 // Test that if there's not a full frame, we fail to parse it.
599 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
600 SpdyFramer framer(spdy_version_);
601 framer.set_enable_compression(false);
603 // Encode the header block into a SynStream frame.
604 SpdySynStreamIR syn_stream(1);
605 syn_stream.set_priority(1);
606 syn_stream.SetHeader("alpha", "beta");
607 syn_stream.SetHeader("gamma", "charlie");
608 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
609 EXPECT_TRUE(frame.get() != NULL);
611 base::StringPiece serialized_headers =
612 GetSerializedHeaders(frame.get(), framer);
613 SpdyHeaderBlock new_headers;
614 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
615 serialized_headers.size() - 2,
619 TEST_P(SpdyFramerTest, OutOfOrderHeaders) {
620 SpdyFramer framer(spdy_version_);
621 framer.set_enable_compression(false);
623 // Frame builder with plentiful buffer size.
624 SpdyFrameBuilder frame(1024);
625 if (spdy_version_ < 4) {
626 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
627 frame.WriteUInt32(3); // stream_id
629 frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3);
632 frame.WriteUInt32(0); // Associated stream id
633 frame.WriteUInt16(0); // Priority.
636 frame.WriteUInt16(2); // Number of headers.
637 frame.WriteString("gamma");
638 frame.WriteString("gamma");
639 frame.WriteString("alpha");
640 frame.WriteString("alpha");
642 frame.WriteUInt32(2); // Number of headers.
643 frame.WriteStringPiece32("gamma");
644 frame.WriteStringPiece32("gamma");
645 frame.WriteStringPiece32("alpha");
646 frame.WriteStringPiece32("alpha");
649 frame.RewriteLength(framer);
651 SpdyHeaderBlock new_headers;
652 scoped_ptr<SpdyFrame> control_frame(frame.take());
653 base::StringPiece serialized_headers =
654 GetSerializedHeaders(control_frame.get(), framer);
655 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
656 serialized_headers.size(),
660 // Test that if we receive a SYN_STREAM with stream ID zero, we signal an error
661 // (but don't crash).
662 TEST_P(SpdyFramerTest, SynStreamWithStreamIdZero) {
663 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
664 SpdyFramer framer(spdy_version_);
665 framer.set_visitor(&visitor);
667 SpdySynStreamIR syn_stream(0);
668 syn_stream.set_priority(1);
669 syn_stream.SetHeader("alpha", "beta");
670 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
671 ASSERT_TRUE(frame.get() != NULL);
673 // We shouldn't have to read the whole frame before we signal an error.
674 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
675 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
676 EXPECT_TRUE(framer.HasError());
677 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
678 << SpdyFramer::ErrorCodeToString(framer.error_code());
681 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
682 // (but don't crash).
683 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
684 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
685 SpdyFramer framer(spdy_version_);
686 framer.set_visitor(&visitor);
688 SpdySynReplyIR syn_reply(0);
689 syn_reply.SetHeader("alpha", "beta");
690 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
691 ASSERT_TRUE(frame.get() != NULL);
693 // We shouldn't have to read the whole frame before we signal an error.
694 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
695 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
696 EXPECT_TRUE(framer.HasError());
697 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
698 << SpdyFramer::ErrorCodeToString(framer.error_code());
701 // Test that if we receive a HEADERS with stream ID zero, we signal an error
702 // (but don't crash).
703 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
704 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
705 SpdyFramer framer(spdy_version_);
706 framer.set_visitor(&visitor);
708 SpdyHeadersIR headers_ir(0);
709 headers_ir.SetHeader("alpha", "beta");
710 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
711 ASSERT_TRUE(frame.get() != NULL);
713 // We shouldn't have to read the whole frame before we signal an error.
714 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
715 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
716 EXPECT_TRUE(framer.HasError());
717 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
718 << SpdyFramer::ErrorCodeToString(framer.error_code());
721 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
722 // error (but don't crash).
723 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
724 if (spdy_version_ < SPDY4) {
728 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
729 SpdyFramer framer(spdy_version_);
730 framer.set_visitor(&visitor);
732 SpdyPushPromiseIR push_promise(0, 4);
733 push_promise.SetHeader("alpha", "beta");
734 scoped_ptr<SpdySerializedFrame> frame(
735 framer.SerializePushPromise(push_promise));
736 ASSERT_TRUE(frame.get() != NULL);
738 // We shouldn't have to read the whole frame before we signal an error.
739 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
740 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
741 EXPECT_TRUE(framer.HasError());
742 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
743 << SpdyFramer::ErrorCodeToString(framer.error_code());
746 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
747 // signal an error (but don't crash).
748 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
749 if (spdy_version_ < SPDY4) {
753 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
754 SpdyFramer framer(spdy_version_);
755 framer.set_visitor(&visitor);
757 SpdyPushPromiseIR push_promise(3, 0);
758 push_promise.SetHeader("alpha", "beta");
759 scoped_ptr<SpdySerializedFrame> frame(
760 framer.SerializePushPromise(push_promise));
761 ASSERT_TRUE(frame.get() != NULL);
763 // We shouldn't have to read the whole frame before we signal an error.
764 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
765 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
766 EXPECT_TRUE(framer.HasError());
767 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
768 << SpdyFramer::ErrorCodeToString(framer.error_code());
771 TEST_P(SpdyFramerTest, DuplicateHeader) {
772 SpdyFramer framer(spdy_version_);
773 // Frame builder with plentiful buffer size.
774 SpdyFrameBuilder frame(1024);
775 if (spdy_version_ < 4) {
776 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
777 frame.WriteUInt32(3); // stream_id
778 frame.WriteUInt32(0); // associated stream id
779 frame.WriteUInt16(0); // Priority.
781 frame.WriteFramePrefix(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
782 frame.WriteUInt32(framer.GetHighestPriority());
786 frame.WriteUInt16(2); // Number of headers.
787 frame.WriteString("name");
788 frame.WriteString("value1");
789 frame.WriteString("name");
790 frame.WriteString("value2");
792 frame.WriteUInt32(2); // Number of headers.
793 frame.WriteStringPiece32("name");
794 frame.WriteStringPiece32("value1");
795 frame.WriteStringPiece32("name");
796 frame.WriteStringPiece32("value2");
799 frame.RewriteLength(framer);
801 SpdyHeaderBlock new_headers;
802 framer.set_enable_compression(false);
803 scoped_ptr<SpdyFrame> control_frame(frame.take());
804 base::StringPiece serialized_headers =
805 GetSerializedHeaders(control_frame.get(), framer);
806 // This should fail because duplicate headers are verboten by the spec.
807 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
808 serialized_headers.size(),
812 TEST_P(SpdyFramerTest, MultiValueHeader) {
813 SpdyFramer framer(spdy_version_);
814 // Frame builder with plentiful buffer size.
815 SpdyFrameBuilder frame(1024);
816 if (spdy_version_ < 4) {
817 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
818 frame.WriteUInt32(3); // stream_id
819 frame.WriteUInt32(0); // associated stream id
820 frame.WriteUInt16(0); // Priority.
822 frame.WriteFramePrefix(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
823 frame.WriteUInt32(framer.GetHighestPriority());
826 string value("value1\0value2");
828 frame.WriteUInt16(1); // Number of headers.
829 frame.WriteString("name");
830 frame.WriteString(value);
832 frame.WriteUInt32(1); // Number of headers.
833 frame.WriteStringPiece32("name");
834 frame.WriteStringPiece32(value);
837 frame.RewriteLength(framer);
839 SpdyHeaderBlock new_headers;
840 framer.set_enable_compression(false);
841 scoped_ptr<SpdyFrame> control_frame(frame.take());
842 base::StringPiece serialized_headers =
843 GetSerializedHeaders(control_frame.get(), framer);
844 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
845 serialized_headers.size(),
847 EXPECT_TRUE(new_headers.find("name") != new_headers.end());
848 EXPECT_EQ(value, new_headers.find("name")->second);
851 TEST_P(SpdyFramerTest, BasicCompression) {
852 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
853 SpdyFramer framer(spdy_version_);
854 framer.set_debug_visitor(visitor.get());
855 SpdySynStreamIR syn_stream(1);
856 syn_stream.set_priority(1);
857 syn_stream.SetHeader("server", "SpdyServer 1.0");
858 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
859 syn_stream.SetHeader("status", "200");
860 syn_stream.SetHeader("version", "HTTP/1.1");
861 syn_stream.SetHeader("content-type", "text/html");
862 syn_stream.SetHeader("content-length", "12");
863 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
864 size_t uncompressed_size1 = visitor->last_payload_len_;
865 size_t compressed_size1 =
866 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
868 EXPECT_EQ(139u, uncompressed_size1);
869 #if defined(USE_SYSTEM_ZLIB)
870 EXPECT_EQ(155u, compressed_size1);
871 #else // !defined(USE_SYSTEM_ZLIB)
872 EXPECT_EQ(135u, compressed_size1);
873 #endif // !defined(USE_SYSTEM_ZLIB)
875 EXPECT_EQ(165u, uncompressed_size1);
876 #if defined(USE_SYSTEM_ZLIB)
877 EXPECT_EQ(181u, compressed_size1);
878 #else // !defined(USE_SYSTEM_ZLIB)
879 EXPECT_EQ(117u, compressed_size1);
880 #endif // !defined(USE_SYSTEM_ZLIB)
882 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
883 size_t uncompressed_size2 = visitor->last_payload_len_;
884 size_t compressed_size2 =
885 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
887 // Expect the second frame to be more compact than the first.
888 EXPECT_LE(frame2->size(), frame1->size());
890 // Decompress the first frame
891 scoped_ptr<SpdyFrame> frame3(SpdyFramerTestUtil::DecompressFrame(
892 &framer, *frame1.get()));
894 // Decompress the second frame
895 visitor.reset(new TestSpdyVisitor(spdy_version_));
896 framer.set_debug_visitor(visitor.get());
897 scoped_ptr<SpdyFrame> frame4(SpdyFramerTestUtil::DecompressFrame(
898 &framer, *frame2.get()));
899 size_t uncompressed_size4 =
900 frame4->size() - framer.GetSynStreamMinimumSize();
901 size_t compressed_size4 =
902 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
904 EXPECT_EQ(139u, uncompressed_size4);
905 #if defined(USE_SYSTEM_ZLIB)
906 EXPECT_EQ(149u, compressed_size4);
907 #else // !defined(USE_SYSTEM_ZLIB)
908 EXPECT_EQ(101u, compressed_size4);
909 #endif // !defined(USE_SYSTEM_ZLIB)
911 EXPECT_EQ(165u, uncompressed_size4);
912 #if defined(USE_SYSTEM_ZLIB)
913 EXPECT_EQ(175u, compressed_size4);
914 #else // !defined(USE_SYSTEM_ZLIB)
915 EXPECT_EQ(102u, compressed_size4);
916 #endif // !defined(USE_SYSTEM_ZLIB)
919 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
920 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
921 EXPECT_EQ(compressed_size2, compressed_size4);
923 // Expect frames 3 & 4 to be the same.
924 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
926 // Expect frames 3 to be the same as a uncompressed frame created
928 framer.set_enable_compression(false);
929 scoped_ptr<SpdyFrame> uncompressed_frame(
930 framer.SerializeSynStream(syn_stream));
931 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
934 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
935 // See crbug.com/172383
936 SpdySynStreamIR syn_stream(1);
937 syn_stream.SetHeader("server", "SpdyServer 1.0");
938 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
939 syn_stream.SetHeader("status", "200");
940 syn_stream.SetHeader("version", "HTTP/1.1");
941 syn_stream.SetHeader("content-type", "text/html");
942 syn_stream.SetHeader("content-length", "12");
943 syn_stream.SetHeader("x-empty-header", "");
945 SpdyFramer framer(spdy_version_);
946 framer.set_enable_compression(true);
947 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
950 TEST_P(SpdyFramerTest, Basic) {
951 const unsigned char kV2Input[] = {
952 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
953 0x00, 0x00, 0x00, 0x14,
954 0x00, 0x00, 0x00, 0x01,
955 0x00, 0x00, 0x00, 0x00,
956 0x00, 0x00, 0x00, 0x01,
957 0x00, 0x02, 'h', 'h',
958 0x00, 0x02, 'v', 'v',
960 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
961 0x00, 0x00, 0x00, 0x18,
962 0x00, 0x00, 0x00, 0x01,
963 0x00, 0x00, 0x00, 0x02,
964 0x00, 0x02, 'h', '2',
965 0x00, 0x02, 'v', '2',
966 0x00, 0x02, 'h', '3',
967 0x00, 0x02, 'v', '3',
969 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
970 0x00, 0x00, 0x00, 0x0c,
971 0xde, 0xad, 0xbe, 0xef,
972 0xde, 0xad, 0xbe, 0xef,
973 0xde, 0xad, 0xbe, 0xef,
975 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
976 0x00, 0x00, 0x00, 0x0c,
977 0x00, 0x00, 0x00, 0x03,
978 0x00, 0x00, 0x00, 0x00,
979 0x00, 0x00, 0x00, 0x00,
981 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
982 0x00, 0x00, 0x00, 0x08,
983 0xde, 0xad, 0xbe, 0xef,
984 0xde, 0xad, 0xbe, 0xef,
986 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
987 0x00, 0x00, 0x00, 0x04,
988 0xde, 0xad, 0xbe, 0xef,
990 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
991 0x00, 0x00, 0x00, 0x08,
992 0x00, 0x00, 0x00, 0x01,
993 0x00, 0x00, 0x00, 0x00,
995 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
996 0x00, 0x00, 0x00, 0x00,
998 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
999 0x00, 0x00, 0x00, 0x08,
1000 0x00, 0x00, 0x00, 0x03,
1001 0x00, 0x00, 0x00, 0x00,
1004 const unsigned char kV3Input[] = {
1005 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1006 0x00, 0x00, 0x00, 0x1a,
1007 0x00, 0x00, 0x00, 0x01,
1008 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x01, 0x00, 0x00,
1011 0x00, 0x02, 'h', 'h',
1012 0x00, 0x00, 0x00, 0x02,
1015 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1016 0x00, 0x00, 0x00, 0x20,
1017 0x00, 0x00, 0x00, 0x01,
1018 0x00, 0x00, 0x00, 0x02,
1019 0x00, 0x00, 0x00, 0x02,
1021 0x00, 0x00, 0x00, 0x02,
1022 'v', '2', 0x00, 0x00,
1023 0x00, 0x02, 'h', '3',
1024 0x00, 0x00, 0x00, 0x02,
1027 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1028 0x00, 0x00, 0x00, 0x0c,
1029 0xde, 0xad, 0xbe, 0xef,
1030 0xde, 0xad, 0xbe, 0xef,
1031 0xde, 0xad, 0xbe, 0xef,
1033 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1034 0x00, 0x00, 0x00, 0x0e,
1035 0x00, 0x00, 0x00, 0x03,
1036 0x00, 0x00, 0x00, 0x00,
1037 0x00, 0x00, 0x00, 0x00,
1040 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1041 0x00, 0x00, 0x00, 0x08,
1042 0xde, 0xad, 0xbe, 0xef,
1043 0xde, 0xad, 0xbe, 0xef,
1045 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1046 0x00, 0x00, 0x00, 0x04,
1047 0xde, 0xad, 0xbe, 0xef,
1049 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1050 0x00, 0x00, 0x00, 0x08,
1051 0x00, 0x00, 0x00, 0x01,
1052 0x00, 0x00, 0x00, 0x00,
1054 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1055 0x00, 0x00, 0x00, 0x00,
1057 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1058 0x00, 0x00, 0x00, 0x08,
1059 0x00, 0x00, 0x00, 0x03,
1060 0x00, 0x00, 0x00, 0x00,
1063 const unsigned char kV4Input[] = {
1064 0x00, 0x1c, 0x08, 0x08, // SYN_STREAM #1
1065 0x00, 0x00, 0x00, 0x01,
1066 0x00, 0x00, 0x00, 0x00,
1067 0x00, 0x00, 0x00, 0x01,
1068 0x00, 0x00, 0x00, 0x02,
1069 'h', 'h', 0x00, 0x00,
1070 0x00, 0x02, 'v', 'v',
1072 0x00, 0x24, 0x08, 0x00, // HEADERS on Stream #1
1073 0x00, 0x00, 0x00, 0x01,
1074 0x00, 0x00, 0x00, 0x02,
1075 0x00, 0x00, 0x00, 0x02,
1076 'h', '2', 0x00, 0x00,
1077 0x00, 0x02, 'v', '2',
1078 0x00, 0x00, 0x00, 0x02,
1079 'h', '3', 0x00, 0x00,
1080 0x00, 0x02, 'v', '3',
1082 0x00, 0x14, 0x00, 0x00, // DATA on Stream #1
1083 0x00, 0x00, 0x00, 0x01,
1084 0xde, 0xad, 0xbe, 0xef,
1085 0xde, 0xad, 0xbe, 0xef,
1086 0xde, 0xad, 0xbe, 0xef,
1088 0x00, 0x10, 0x08, 0x08, // SYN Stream #3
1089 0x00, 0x00, 0x00, 0x03,
1090 0x00, 0x00, 0x00, 0x00,
1091 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x10, 0x00, 0x00, // DATA on Stream #3
1094 0x00, 0x00, 0x00, 0x03,
1095 0xde, 0xad, 0xbe, 0xef,
1096 0xde, 0xad, 0xbe, 0xef,
1098 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1
1099 0x00, 0x00, 0x00, 0x01,
1100 0xde, 0xad, 0xbe, 0xef,
1102 0x00, 0x0c, 0x03, 0x00, // RST_STREAM on Stream #1
1103 0x00, 0x00, 0x00, 0x01,
1104 0x00, 0x00, 0x00, 0x00,
1106 0x00, 0x08, 0x00, 0x00, // DATA on Stream #3
1107 0x00, 0x00, 0x00, 0x03,
1109 0x00, 0x17, 0x03, 0x00, // RST_STREAM on Stream #3
1110 0x00, 0x00, 0x00, 0x03,
1111 0x00, 0x00, 0x00, 0x00,
1112 0x52, 0x45, 0x53, 0x45, // opaque data
1113 0x54, 0x53, 0x54, 0x52,
1117 TestSpdyVisitor visitor(spdy_version_);
1119 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1120 } else if (IsSpdy3()) {
1121 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1123 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1126 EXPECT_EQ(2, visitor.syn_frame_count_);
1127 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1128 EXPECT_EQ(1, visitor.headers_frame_count_);
1129 EXPECT_EQ(24, visitor.data_bytes_);
1131 // TODO(jgraettinger): We expect to handle but not emit RST payloads.
1132 if (false /*!FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/ &&
1134 // Last rst_stream is an INVALID_CONTROL_FRAME.
1135 EXPECT_EQ(1, visitor.error_count_);
1136 EXPECT_EQ(1, visitor.fin_frame_count_);
1138 EXPECT_EQ(0, visitor.error_count_);
1139 EXPECT_EQ(2, visitor.fin_frame_count_);
1142 if (true /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/ &&
1144 base::StringPiece reset_stream = "RESETSTREAM";
1145 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1147 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1150 EXPECT_EQ(0, visitor.fin_flag_count_);
1151 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1152 EXPECT_EQ(4, visitor.data_frame_count_);
1153 visitor.fin_opaque_data_.clear();
1156 // Test that the FIN flag on a data frame signifies EOF.
1157 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1158 const unsigned char kV2Input[] = {
1159 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1160 0x00, 0x00, 0x00, 0x14,
1161 0x00, 0x00, 0x00, 0x01,
1162 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x01,
1164 0x00, 0x02, 'h', 'h',
1165 0x00, 0x02, 'v', 'v',
1167 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1168 0x00, 0x00, 0x00, 0x10,
1169 0x00, 0x00, 0x00, 0x01,
1170 0x00, 0x00, 0x00, 0x01,
1171 0x00, 0x02, 'a', 'a',
1172 0x00, 0x02, 'b', 'b',
1174 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1175 0x00, 0x00, 0x00, 0x0c,
1176 0xde, 0xad, 0xbe, 0xef,
1177 0xde, 0xad, 0xbe, 0xef,
1178 0xde, 0xad, 0xbe, 0xef,
1180 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1181 0x01, 0x00, 0x00, 0x04,
1182 0xde, 0xad, 0xbe, 0xef,
1184 const unsigned char kV3Input[] = {
1185 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1186 0x00, 0x00, 0x00, 0x1a,
1187 0x00, 0x00, 0x00, 0x01,
1188 0x00, 0x00, 0x00, 0x00,
1189 0x00, 0x00, 0x00, 0x00,
1190 0x00, 0x01, 0x00, 0x00,
1191 0x00, 0x02, 'h', 'h',
1192 0x00, 0x00, 0x00, 0x02,
1195 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1196 0x00, 0x00, 0x00, 0x14,
1197 0x00, 0x00, 0x00, 0x01,
1198 0x00, 0x00, 0x00, 0x01,
1199 0x00, 0x00, 0x00, 0x02,
1200 'a', 'a', 0x00, 0x00,
1201 0x00, 0x02, 'b', 'b',
1203 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1204 0x00, 0x00, 0x00, 0x0c,
1205 0xde, 0xad, 0xbe, 0xef,
1206 0xde, 0xad, 0xbe, 0xef,
1207 0xde, 0xad, 0xbe, 0xef,
1209 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1210 0x01, 0x00, 0x00, 0x04,
1211 0xde, 0xad, 0xbe, 0xef,
1213 const unsigned char kV4Input[] = {
1214 0x00, 0x1c, 0x08, 0x08, // SYN_STREAM #1
1215 0x00, 0x00, 0x00, 0x01,
1216 0x00, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x01,
1218 0x00, 0x00, 0x00, 0x02,
1219 'h', 'h', 0x00, 0x00,
1220 0x00, 0x02, 'v', 'v',
1222 0x00, 0x18, 0x08, 0x00, // SYN REPLY Stream #1
1223 0x00, 0x00, 0x00, 0x01,
1224 0x00, 0x00, 0x00, 0x01,
1225 0x00, 0x00, 0x00, 0x02,
1226 'a', 'a', 0x00, 0x00,
1227 0x00, 0x02, 'b', 'b',
1229 0x00, 0x14, 0x00, 0x00, // DATA on Stream #1
1230 0x00, 0x00, 0x00, 0x01,
1231 0xde, 0xad, 0xbe, 0xef,
1232 0xde, 0xad, 0xbe, 0xef,
1233 0xde, 0xad, 0xbe, 0xef,
1235 0x00, 0x0c, 0x00, 0x01, // DATA on Stream #1, with FIN
1236 0x00, 0x00, 0x00, 0x01,
1237 0xde, 0xad, 0xbe, 0xef,
1240 TestSpdyVisitor visitor(spdy_version_);
1242 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1243 } else if (IsSpdy3()) {
1244 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1246 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1249 EXPECT_EQ(0, visitor.error_count_);
1250 EXPECT_EQ(1, visitor.syn_frame_count_);
1252 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1253 EXPECT_EQ(1, visitor.headers_frame_count_);
1255 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1256 EXPECT_EQ(0, visitor.headers_frame_count_);
1258 EXPECT_EQ(16, visitor.data_bytes_);
1259 EXPECT_EQ(0, visitor.fin_frame_count_);
1260 EXPECT_EQ(0, visitor.fin_flag_count_);
1261 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1262 EXPECT_EQ(2, visitor.data_frame_count_);
1265 // Test that the FIN flag on a SYN reply frame signifies EOF.
1266 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1267 const unsigned char kV2Input[] = {
1268 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1269 0x00, 0x00, 0x00, 0x14,
1270 0x00, 0x00, 0x00, 0x01,
1271 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x01,
1273 0x00, 0x02, 'h', 'h',
1274 0x00, 0x02, 'v', 'v',
1276 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1277 0x01, 0x00, 0x00, 0x10,
1278 0x00, 0x00, 0x00, 0x01,
1279 0x00, 0x00, 0x00, 0x01,
1280 0x00, 0x02, 'a', 'a',
1281 0x00, 0x02, 'b', 'b',
1283 const unsigned char kV3Input[] = {
1284 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1285 0x00, 0x00, 0x00, 0x1a,
1286 0x00, 0x00, 0x00, 0x01,
1287 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x01, 0x00, 0x00,
1290 0x00, 0x02, 'h', 'h',
1291 0x00, 0x00, 0x00, 0x02,
1294 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1295 0x01, 0x00, 0x00, 0x14,
1296 0x00, 0x00, 0x00, 0x01,
1297 0x00, 0x00, 0x00, 0x01,
1298 0x00, 0x00, 0x00, 0x02,
1299 'a', 'a', 0x00, 0x00,
1300 0x00, 0x02, 'b', 'b',
1302 const unsigned char kV4Input[] = {
1303 0x00, 0x1c, 0x08, 0x08, // SYN_STREAM #1
1304 0x00, 0x00, 0x00, 0x01,
1305 0x00, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x01,
1307 0x00, 0x00, 0x00, 0x02,
1308 'h', 'h', 0x00, 0x00,
1309 0x00, 0x02, 'v', 'v',
1311 0x00, 0x18, 0x08, 0x01, // SYN_REPLY #1, with FIN
1312 0x00, 0x00, 0x00, 0x01,
1313 0x00, 0x00, 0x00, 0x01,
1314 0x00, 0x00, 0x00, 0x02,
1315 'a', 'a', 0x00, 0x00,
1316 0x00, 0x02, 'b', 'b',
1319 TestSpdyVisitor visitor(spdy_version_);
1321 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1322 } else if (IsSpdy3()) {
1323 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1325 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1328 EXPECT_EQ(0, visitor.error_count_);
1329 EXPECT_EQ(1, visitor.syn_frame_count_);
1331 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1332 EXPECT_EQ(1, visitor.headers_frame_count_);
1334 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1335 EXPECT_EQ(0, visitor.headers_frame_count_);
1337 EXPECT_EQ(0, visitor.data_bytes_);
1338 EXPECT_EQ(0, visitor.fin_frame_count_);
1339 EXPECT_EQ(1, visitor.fin_flag_count_);
1340 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1341 EXPECT_EQ(0, visitor.data_frame_count_);
1344 TEST_P(SpdyFramerTest, HeaderCompression) {
1345 SpdyFramer send_framer(spdy_version_);
1346 SpdyFramer recv_framer(spdy_version_);
1348 send_framer.set_enable_compression(true);
1349 recv_framer.set_enable_compression(true);
1351 const char kHeader1[] = "header1";
1352 const char kHeader2[] = "header2";
1353 const char kHeader3[] = "header3";
1354 const char kValue1[] = "value1";
1355 const char kValue2[] = "value2";
1356 const char kValue3[] = "value3";
1359 SpdyHeaderBlock block;
1360 block[kHeader1] = kValue1;
1361 block[kHeader2] = kValue2;
1362 SpdySynStreamIR syn_ir_1(1);
1363 syn_ir_1.set_name_value_block(block);
1364 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1365 EXPECT_TRUE(syn_frame_1.get() != NULL);
1368 block[kHeader3] = kValue3;
1369 SpdySynStreamIR syn_stream(3);
1370 syn_stream.set_name_value_block(block);
1371 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1372 EXPECT_TRUE(syn_frame_2.get() != NULL);
1374 // Now start decompressing
1375 scoped_ptr<SpdyFrame> decompressed;
1376 scoped_ptr<SpdyFrame> uncompressed;
1377 base::StringPiece serialized_headers;
1378 SpdyHeaderBlock decompressed_headers;
1380 // Decompress SYN_STREAM #1
1381 decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
1382 &recv_framer, *syn_frame_1.get()));
1383 EXPECT_TRUE(decompressed.get() != NULL);
1384 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1385 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1386 serialized_headers.size(),
1387 &decompressed_headers));
1388 EXPECT_EQ(2u, decompressed_headers.size());
1389 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1390 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1392 // Decompress SYN_STREAM #2
1393 decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
1394 &recv_framer, *syn_frame_2.get()));
1395 EXPECT_TRUE(decompressed.get() != NULL);
1396 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1397 decompressed_headers.clear();
1398 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1399 serialized_headers.size(),
1400 &decompressed_headers));
1401 EXPECT_EQ(3u, decompressed_headers.size());
1402 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1403 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1404 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1407 // Verify we don't leak when we leave streams unclosed
1408 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressors) {
1409 SpdyFramer send_framer(spdy_version_);
1411 send_framer.set_enable_compression(true);
1413 const char kHeader1[] = "header1";
1414 const char kHeader2[] = "header2";
1415 const char kValue1[] = "value1";
1416 const char kValue2[] = "value2";
1418 SpdySynStreamIR syn_stream(1);
1419 syn_stream.SetHeader(kHeader1, kValue1);
1420 syn_stream.SetHeader(kHeader2, kValue2);
1421 scoped_ptr<SpdyFrame> syn_frame(send_framer.SerializeSynStream(syn_stream));
1422 EXPECT_TRUE(syn_frame.get() != NULL);
1424 StringPiece bytes = "this is a test test test test test!";
1425 net::SpdyDataIR data_ir(1, bytes);
1426 data_ir.set_fin(true);
1427 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1428 EXPECT_TRUE(send_frame.get() != NULL);
1430 // Run the inputs through the framer.
1431 TestSpdyVisitor visitor(spdy_version_);
1432 visitor.use_compression_ = true;
1433 const unsigned char* data;
1434 data = reinterpret_cast<const unsigned char*>(syn_frame->data());
1435 visitor.SimulateInFramer(data, syn_frame->size());
1436 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1437 visitor.SimulateInFramer(data, send_frame->size());
1439 EXPECT_EQ(0, visitor.error_count_);
1440 EXPECT_EQ(1, visitor.syn_frame_count_);
1441 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1442 EXPECT_EQ(0, visitor.headers_frame_count_);
1443 EXPECT_EQ(bytes.size(), static_cast<unsigned>(visitor.data_bytes_));
1444 EXPECT_EQ(0, visitor.fin_frame_count_);
1445 EXPECT_EQ(0, visitor.fin_flag_count_);
1446 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1447 EXPECT_EQ(1, visitor.data_frame_count_);
1450 // Verify we can decompress the stream even if handed over to the
1451 // framer 1 byte at a time.
1452 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1453 SpdyFramer send_framer(spdy_version_);
1455 send_framer.set_enable_compression(true);
1457 const char kHeader1[] = "header1";
1458 const char kHeader2[] = "header2";
1459 const char kValue1[] = "value1";
1460 const char kValue2[] = "value2";
1462 SpdySynStreamIR syn_stream(1);
1463 syn_stream.SetHeader(kHeader1, kValue1);
1464 syn_stream.SetHeader(kHeader2, kValue2);
1465 scoped_ptr<SpdyFrame> syn_frame(send_framer.SerializeSynStream(syn_stream));
1466 EXPECT_TRUE(syn_frame.get() != NULL);
1468 const char bytes[] = "this is a test test test test test!";
1469 net::SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1470 data_ir.set_fin(true);
1471 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1472 EXPECT_TRUE(send_frame.get() != NULL);
1474 // Run the inputs through the framer.
1475 TestSpdyVisitor visitor(spdy_version_);
1476 visitor.use_compression_ = true;
1477 const unsigned char* data;
1478 data = reinterpret_cast<const unsigned char*>(syn_frame->data());
1479 for (size_t idx = 0; idx < syn_frame->size(); ++idx) {
1480 visitor.SimulateInFramer(data + idx, 1);
1481 ASSERT_EQ(0, visitor.error_count_);
1483 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1484 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1485 visitor.SimulateInFramer(data + idx, 1);
1486 ASSERT_EQ(0, visitor.error_count_);
1489 EXPECT_EQ(0, visitor.error_count_);
1490 EXPECT_EQ(1, visitor.syn_frame_count_);
1491 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1492 EXPECT_EQ(0, visitor.headers_frame_count_);
1493 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1494 EXPECT_EQ(0, visitor.fin_frame_count_);
1495 EXPECT_EQ(0, visitor.fin_flag_count_);
1496 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1497 EXPECT_EQ(1, visitor.data_frame_count_);
1500 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1501 SpdyFramer framer(spdy_version_);
1502 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1503 net::SpdyWindowUpdateIR(1, 0x12345678)));
1505 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1506 const unsigned char kV3FrameData[] = { // Also applies for V2.
1507 0x80, spdy_version_ch_, 0x00, 0x09,
1508 0x00, 0x00, 0x00, 0x08,
1509 0x00, 0x00, 0x00, 0x01,
1510 0x12, 0x34, 0x56, 0x78
1512 const unsigned char kV4FrameData[] = {
1513 0x00, 0x0c, 0x09, 0x00,
1514 0x00, 0x00, 0x00, 0x01,
1515 0x12, 0x34, 0x56, 0x78
1519 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1521 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1525 TEST_P(SpdyFramerTest, CreateDataFrame) {
1526 SpdyFramer framer(spdy_version_);
1529 const char kDescription[] = "'hello' data frame, no FIN";
1530 const unsigned char kV3FrameData[] = { // Also applies for V2.
1531 0x00, 0x00, 0x00, 0x01,
1532 0x00, 0x00, 0x00, 0x05,
1536 const unsigned char kV4FrameData[] = {
1537 0x00, 0x0d, 0x00, 0x00,
1538 0x00, 0x00, 0x00, 0x01,
1542 const char bytes[] = "hello";
1544 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1545 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1548 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1551 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1554 SpdyDataIR data_header_ir(1);
1555 data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
1556 frame.reset(framer.SerializeDataFrameHeader(data_header_ir));
1557 CompareCharArraysWithHexError(
1559 reinterpret_cast<const unsigned char*>(frame->data()),
1560 framer.GetDataFrameMinimumSize(),
1561 IsSpdy4() ? kV4FrameData : kV3FrameData,
1562 framer.GetDataFrameMinimumSize());
1566 const char kDescription[] = "Data frame with negative data byte, no FIN";
1567 const unsigned char kV3FrameData[] = { // Also applies for V2.
1568 0x00, 0x00, 0x00, 0x01,
1569 0x00, 0x00, 0x00, 0x01,
1572 const unsigned char kV4FrameData[] = {
1573 0x00, 0x09, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x01,
1577 net::SpdyDataIR data_ir(1, StringPiece("\xff", 1));
1578 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1581 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1584 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1589 const char kDescription[] = "'hello' data frame, with FIN";
1590 const unsigned char kV3FrameData[] = { // Also applies for V2.
1591 0x00, 0x00, 0x00, 0x01,
1592 0x01, 0x00, 0x00, 0x05,
1596 const unsigned char kV4FrameData[] = {
1597 0x00, 0x0d, 0x00, 0x01,
1598 0x00, 0x00, 0x00, 0x01,
1602 net::SpdyDataIR data_ir(1, StringPiece("hello", 5));
1603 data_ir.set_fin(true);
1604 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1607 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1610 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1615 const char kDescription[] = "Empty data frame";
1616 const unsigned char kV3FrameData[] = { // Also applies for V2.
1617 0x00, 0x00, 0x00, 0x01,
1618 0x00, 0x00, 0x00, 0x00,
1620 const unsigned char kV4FrameData[] = {
1621 0x00, 0x08, 0x00, 0x00,
1622 0x00, 0x00, 0x00, 0x01,
1624 net::SpdyDataIR data_ir(1, StringPiece());
1625 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1628 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1631 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1636 const char kDescription[] = "Data frame with max stream ID";
1637 const unsigned char kV3FrameData[] = { // Also applies for V2.
1638 0x7f, 0xff, 0xff, 0xff,
1639 0x01, 0x00, 0x00, 0x05,
1643 const unsigned char kV4FrameData[] = {
1644 0x00, 0x0d, 0x00, 0x01,
1645 0x7f, 0xff, 0xff, 0xff,
1649 net::SpdyDataIR data_ir(0x7fffffff, "hello");
1650 data_ir.set_fin(true);
1651 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1654 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1657 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1662 // This test does not apply to SPDY 4 because the max frame size is smaller
1664 const char kDescription[] = "Large data frame";
1665 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1666 const string kData(kDataSize, 'A');
1667 const unsigned char kFrameHeader[] = {
1668 0x00, 0x00, 0x00, 0x01,
1669 0x01, 0x40, 0x00, 0x00,
1672 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1673 scoped_ptr<unsigned char[]> expected_frame_data(
1674 new unsigned char[kFrameSize]);
1675 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1676 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1678 net::SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
1679 data_ir.set_fin(true);
1680 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1681 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1685 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1686 SpdyFramer framer(spdy_version_);
1687 framer.set_enable_compression(false);
1690 const char kDescription[] = "SYN_STREAM frame, lowest pri, slot 2, no FIN";
1692 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1693 const unsigned char kCre = IsSpdy2() ? 0 : 2;
1694 const unsigned char kV2FrameData[] = {
1695 0x80, spdy_version_ch_, 0x00, 0x01,
1696 0x00, 0x00, 0x00, 0x20,
1697 0x00, 0x00, 0x00, 0x01,
1698 0x00, 0x00, 0x00, 0x00,
1699 kPri, 0x00, 0x00, 0x02,
1700 0x00, 0x03, 'b', 'a',
1701 'r', 0x00, 0x03, 'f',
1702 'o', 'o', 0x00, 0x03,
1703 'f', 'o', 'o', 0x00,
1706 const unsigned char kV3FrameData[] = {
1707 0x80, spdy_version_ch_, 0x00, 0x01,
1708 0x00, 0x00, 0x00, 0x2a,
1709 0x00, 0x00, 0x00, 0x01,
1710 0x00, 0x00, 0x00, 0x00,
1711 kPri, kCre, 0x00, 0x00,
1712 0x00, 0x02, 0x00, 0x00,
1713 0x00, 0x03, 'b', 'a',
1714 'r', 0x00, 0x00, 0x00,
1715 0x03, 'f', 'o', 'o',
1716 0x00, 0x00, 0x00, 0x03,
1717 'f', 'o', 'o', 0x00,
1718 0x00, 0x00, 0x03, 'b',
1721 const unsigned char kV4FrameData[] = {
1722 0x00, 0x2c, 0x08, 0x08,
1723 0x00, 0x00, 0x00, 0x01,
1724 0x00, 0x00, 0x00, 0x07,
1725 0x00, 0x00, 0x00, 0x02,
1726 0x00, 0x00, 0x00, 0x03,
1727 'b', 'a', 'r', 0x00,
1728 0x00, 0x00, 0x03, 'f',
1729 'o', 'o', 0x00, 0x00,
1730 0x00, 0x03, 'f', 'o',
1731 'o', 0x00, 0x00, 0x00,
1734 SpdySynStreamIR syn_stream(1);
1735 syn_stream.set_priority(framer.GetLowestPriority());
1736 syn_stream.set_slot(kCre);
1737 syn_stream.SetHeader("bar", "foo");
1738 syn_stream.SetHeader("foo", "bar");
1739 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1741 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1742 } else if (IsSpdy3()) {
1743 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1745 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1750 const char kDescription[] =
1751 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1754 const unsigned char kV2FrameData[] = {
1755 0x80, spdy_version_ch_, 0x00, 0x01,
1756 0x01, 0x00, 0x00, 0x1D,
1757 0x7f, 0xff, 0xff, 0xff,
1758 0x7f, 0xff, 0xff, 0xff,
1759 0x00, 0x00, 0x00, 0x02,
1760 0x00, 0x00, 0x00, 0x03,
1761 'f', 'o', 'o', 0x00,
1762 0x03, 'f', 'o', 'o',
1763 0x00, 0x03, 'b', 'a',
1766 const unsigned char kV3FrameData[] = {
1767 0x80, spdy_version_ch_, 0x00, 0x01,
1768 0x01, 0x00, 0x00, 0x27,
1769 0x7f, 0xff, 0xff, 0xff,
1770 0x7f, 0xff, 0xff, 0xff,
1771 0x00, 0x00, 0x00, 0x00,
1772 0x00, 0x02, 0x00, 0x00,
1773 0x00, 0x00, 0x00, 0x00,
1774 0x00, 0x03, 'f', 'o',
1775 'o', 0x00, 0x00, 0x00,
1776 0x03, 'f', 'o', 'o',
1777 0x00, 0x00, 0x00, 0x03,
1780 const unsigned char kV4FrameData[] = {
1781 0x00, 0x29, 0x08, 0x09,
1782 0x7f, 0xff, 0xff, 0xff,
1783 0x00, 0x00, 0x00, 0x00,
1784 0x00, 0x00, 0x00, 0x02,
1785 0x00, 0x00, 0x00, 0x00,
1786 0x00, 0x00, 0x00, 0x03,
1787 'f', 'o', 'o', 0x00,
1788 0x00, 0x00, 0x03, 'f',
1789 'o', 'o', 0x00, 0x00,
1790 0x00, 0x03, 'b', 'a',
1793 SpdySynStreamIR syn_stream(0x7fffffff);
1794 syn_stream.set_associated_to_stream_id(0x7fffffff);
1795 syn_stream.set_priority(framer.GetHighestPriority());
1796 syn_stream.set_fin(true);
1797 syn_stream.SetHeader("", "foo");
1798 syn_stream.SetHeader("foo", "bar");
1799 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1801 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1802 } else if (IsSpdy3()) {
1803 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1805 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1810 const char kDescription[] =
1811 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1814 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
1815 const unsigned char kV2FrameData[] = {
1816 0x80, spdy_version_ch_, 0x00, 0x01,
1817 0x01, 0x00, 0x00, 0x1D,
1818 0x7f, 0xff, 0xff, 0xff,
1819 0x7f, 0xff, 0xff, 0xff,
1820 kPri, 0x00, 0x00, 0x02,
1821 0x00, 0x03, 'b', 'a',
1822 'r', 0x00, 0x03, 'f',
1823 'o', 'o', 0x00, 0x03,
1824 'f', 'o', 'o', 0x00,
1827 const unsigned char kV3FrameData[] = {
1828 0x80, spdy_version_ch_, 0x00, 0x01,
1829 0x01, 0x00, 0x00, 0x27,
1830 0x7f, 0xff, 0xff, 0xff,
1831 0x7f, 0xff, 0xff, 0xff,
1832 kPri, 0x00, 0x00, 0x00,
1833 0x00, 0x02, 0x00, 0x00,
1834 0x00, 0x03, 'b', 'a',
1835 'r', 0x00, 0x00, 0x00,
1836 0x03, 'f', 'o', 'o',
1837 0x00, 0x00, 0x00, 0x03,
1838 'f', 'o', 'o', 0x00,
1841 const unsigned char kV4FrameData[] = {
1842 0x00, 0x29, 0x08, 0x09,
1843 0x7f, 0xff, 0xff, 0xff,
1844 0x00, 0x00, 0x00, 0x01,
1845 0x00, 0x00, 0x00, 0x02,
1846 0x00, 0x00, 0x00, 0x03,
1847 'b', 'a', 'r', 0x00,
1848 0x00, 0x00, 0x03, 'f',
1849 'o', 'o', 0x00, 0x00,
1850 0x00, 0x03, 'f', 'o',
1851 'o', 0x00, 0x00, 0x00,
1854 SpdySynStreamIR syn_stream(0x7fffffff);
1855 syn_stream.set_associated_to_stream_id(0x7fffffff);
1856 syn_stream.set_priority(1);
1857 syn_stream.set_fin(true);
1858 syn_stream.SetHeader("bar", "foo");
1859 syn_stream.SetHeader("foo", "");
1860 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1862 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1863 } else if (IsSpdy3()) {
1864 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1866 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1871 // TODO(phajdan.jr): Clean up after we no longer need
1872 // to workaround http://crbug.com/139744.
1873 #if !defined(USE_SYSTEM_ZLIB)
1874 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
1875 SpdyFramer framer(spdy_version_);
1876 framer.set_enable_compression(true);
1879 const char kDescription[] =
1880 "SYN_STREAM frame, low pri, no FIN";
1882 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
1883 const unsigned char kV2FrameData[] = {
1884 0x80, spdy_version_ch_, 0x00, 0x01,
1885 0x00, 0x00, 0x00, 0x36,
1886 0x00, 0x00, 0x00, 0x01,
1887 0x00, 0x00, 0x00, 0x00,
1888 0x80, 0x00, 0x38, 0xea,
1889 0xdf, 0xa2, 0x51, 0xb2,
1890 0x62, 0x60, 0x62, 0x60,
1891 0x4e, 0x4a, 0x2c, 0x62,
1892 0x60, 0x06, 0x08, 0xa0,
1893 0xb4, 0xfc, 0x7c, 0x80,
1894 0x00, 0x62, 0x60, 0x4e,
1895 0xcb, 0xcf, 0x67, 0x60,
1896 0x06, 0x08, 0xa0, 0xa4,
1897 0xc4, 0x22, 0x80, 0x00,
1898 0x02, 0x00, 0x00, 0x00,
1901 const unsigned char kV3FrameData[] = {
1902 0x80, spdy_version_ch_, 0x00, 0x01,
1903 0x00, 0x00, 0x00, 0x37,
1904 0x00, 0x00, 0x00, 0x01,
1905 0x00, 0x00, 0x00, 0x00,
1906 0x80, 0x00, 0x38, 0xEA,
1907 0xE3, 0xC6, 0xA7, 0xC2,
1908 0x02, 0xE5, 0x0E, 0x50,
1909 0xC2, 0x4B, 0x4A, 0x04,
1910 0xE5, 0x0B, 0x66, 0x80,
1911 0x00, 0x4A, 0xCB, 0xCF,
1912 0x07, 0x08, 0x20, 0x10,
1913 0x95, 0x96, 0x9F, 0x0F,
1914 0xA2, 0x00, 0x02, 0x28,
1915 0x29, 0xB1, 0x08, 0x20,
1916 0x80, 0x00, 0x00, 0x00,
1919 const unsigned char kV4FrameData[] = {
1920 0x00, 0x39, 0x08, 0x08,
1921 0x00, 0x00, 0x00, 0x01,
1922 0x00, 0x00, 0x00, 0x04,
1923 0x38, 0xea, 0xe3, 0xc6,
1924 0xa7, 0xc2, 0x02, 0xe5,
1925 0x0e, 0x50, 0xc2, 0x4b,
1926 0x4a, 0x04, 0xe5, 0x0b,
1927 0x66, 0x80, 0x00, 0x4a,
1928 0xcb, 0xcf, 0x07, 0x08,
1929 0x20, 0x10, 0x95, 0x96,
1930 0x9f, 0x0f, 0xa2, 0x00,
1931 0x02, 0x28, 0x29, 0xb1,
1932 0x08, 0x20, 0x80, 0x00,
1933 0x00, 0x00, 0x00, 0xff,
1936 SpdySynStreamIR syn_stream(1);
1937 syn_stream.set_priority(priority);
1938 syn_stream.SetHeader("bar", "foo");
1939 syn_stream.SetHeader("foo", "bar");
1940 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1942 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1943 } else if (IsSpdy3()) {
1944 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1946 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1950 #endif // !defined(USE_SYSTEM_ZLIB)
1952 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
1953 SpdyFramer framer(spdy_version_);
1954 framer.set_enable_compression(false);
1957 const char kDescription[] = "SYN_REPLY frame, no FIN";
1959 const unsigned char kV2FrameData[] = {
1960 0x80, spdy_version_ch_, 0x00, 0x02,
1961 0x00, 0x00, 0x00, 0x1C,
1962 0x00, 0x00, 0x00, 0x01,
1963 0x00, 0x00, 0x00, 0x02,
1964 0x00, 0x03, 'b', 'a',
1965 'r', 0x00, 0x03, 'f',
1966 'o', 'o', 0x00, 0x03,
1967 'f', 'o', 'o', 0x00,
1970 const unsigned char kV3FrameData[] = {
1971 0x80, spdy_version_ch_, 0x00, 0x02,
1972 0x00, 0x00, 0x00, 0x24,
1973 0x00, 0x00, 0x00, 0x01,
1974 0x00, 0x00, 0x00, 0x02,
1975 0x00, 0x00, 0x00, 0x03,
1976 'b', 'a', 'r', 0x00,
1977 0x00, 0x00, 0x03, 'f',
1978 'o', 'o', 0x00, 0x00,
1979 0x00, 0x03, 'f', 'o',
1980 'o', 0x00, 0x00, 0x00,
1983 const unsigned char kV4FrameData[] = {
1984 0x00, 0x28, 0x08, 0x00,
1985 0x00, 0x00, 0x00, 0x01,
1986 0x00, 0x00, 0x00, 0x02,
1987 0x00, 0x00, 0x00, 0x03,
1988 'b', 'a', 'r', 0x00,
1989 0x00, 0x00, 0x03, 'f',
1990 'o', 'o', 0x00, 0x00,
1991 0x00, 0x03, 'f', 'o',
1992 'o', 0x00, 0x00, 0x00,
1995 SpdySynReplyIR syn_reply(1);
1996 syn_reply.SetHeader("bar", "foo");
1997 syn_reply.SetHeader("foo", "bar");
1998 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2000 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2001 } else if (IsSpdy3()) {
2002 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2004 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2009 const char kDescription[] =
2010 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2012 const unsigned char kV2FrameData[] = {
2013 0x80, spdy_version_ch_, 0x00, 0x02,
2014 0x01, 0x00, 0x00, 0x19,
2015 0x7f, 0xff, 0xff, 0xff,
2016 0x00, 0x00, 0x00, 0x02,
2017 0x00, 0x00, 0x00, 0x03,
2018 'f', 'o', 'o', 0x00,
2019 0x03, 'f', 'o', 'o',
2020 0x00, 0x03, 'b', 'a',
2023 const unsigned char kV3FrameData[] = {
2024 0x80, spdy_version_ch_, 0x00, 0x02,
2025 0x01, 0x00, 0x00, 0x21,
2026 0x7f, 0xff, 0xff, 0xff,
2027 0x00, 0x00, 0x00, 0x02,
2028 0x00, 0x00, 0x00, 0x00,
2029 0x00, 0x00, 0x00, 0x03,
2030 'f', 'o', 'o', 0x00,
2031 0x00, 0x00, 0x03, 'f',
2032 'o', 'o', 0x00, 0x00,
2033 0x00, 0x03, 'b', 'a',
2036 const unsigned char kV4FrameData[] = {
2037 0x00, 0x25, 0x08, 0x01,
2038 0x7f, 0xff, 0xff, 0xff,
2039 0x00, 0x00, 0x00, 0x02,
2040 0x00, 0x00, 0x00, 0x00,
2041 0x00, 0x00, 0x00, 0x03,
2042 'f', 'o', 'o', 0x00,
2043 0x00, 0x00, 0x03, 'f',
2044 'o', 'o', 0x00, 0x00,
2045 0x00, 0x03, 'b', 'a',
2048 SpdySynReplyIR syn_reply(0x7fffffff);
2049 syn_reply.set_fin(true);
2050 syn_reply.SetHeader("", "foo");
2051 syn_reply.SetHeader("foo", "bar");
2052 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2054 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2055 } else if (IsSpdy3()) {
2056 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2058 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2063 const char kDescription[] =
2064 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2066 const unsigned char kV2FrameData[] = {
2067 0x80, spdy_version_ch_, 0x00, 0x02,
2068 0x01, 0x00, 0x00, 0x19,
2069 0x7f, 0xff, 0xff, 0xff,
2070 0x00, 0x00, 0x00, 0x02,
2071 0x00, 0x03, 'b', 'a',
2072 'r', 0x00, 0x03, 'f',
2073 'o', 'o', 0x00, 0x03,
2074 'f', 'o', 'o', 0x00,
2077 const unsigned char kV3FrameData[] = {
2078 0x80, spdy_version_ch_, 0x00, 0x02,
2079 0x01, 0x00, 0x00, 0x21,
2080 0x7f, 0xff, 0xff, 0xff,
2081 0x00, 0x00, 0x00, 0x02,
2082 0x00, 0x00, 0x00, 0x03,
2083 'b', 'a', 'r', 0x00,
2084 0x00, 0x00, 0x03, 'f',
2085 'o', 'o', 0x00, 0x00,
2086 0x00, 0x03, 'f', 'o',
2087 'o', 0x00, 0x00, 0x00,
2090 const unsigned char kV4FrameData[] = {
2091 0x00, 0x25, 0x08, 0x01,
2092 0x7f, 0xff, 0xff, 0xff,
2093 0x00, 0x00, 0x00, 0x02,
2094 0x00, 0x00, 0x00, 0x03,
2095 'b', 'a', 'r', 0x00,
2096 0x00, 0x00, 0x03, 'f',
2097 'o', 'o', 0x00, 0x00,
2098 0x00, 0x03, 'f', 'o',
2099 'o', 0x00, 0x00, 0x00,
2102 SpdySynReplyIR syn_reply(0x7fffffff);
2103 syn_reply.set_fin(true);
2104 syn_reply.SetHeader("bar", "foo");
2105 syn_reply.SetHeader("foo", "");
2106 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2108 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2109 } else if (IsSpdy3()) {
2110 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2112 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2117 // TODO(phajdan.jr): Clean up after we no longer need
2118 // to workaround http://crbug.com/139744.
2119 #if !defined(USE_SYSTEM_ZLIB)
2120 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2121 SpdyFramer framer(spdy_version_);
2122 framer.set_enable_compression(true);
2125 const char kDescription[] = "SYN_REPLY frame, no FIN";
2127 const unsigned char kV2FrameData[] = {
2128 0x80, spdy_version_ch_, 0x00, 0x02,
2129 0x00, 0x00, 0x00, 0x32,
2130 0x00, 0x00, 0x00, 0x01,
2131 0x00, 0x00, 0x38, 0xea,
2132 0xdf, 0xa2, 0x51, 0xb2,
2133 0x62, 0x60, 0x62, 0x60,
2134 0x4e, 0x4a, 0x2c, 0x62,
2135 0x60, 0x06, 0x08, 0xa0,
2136 0xb4, 0xfc, 0x7c, 0x80,
2137 0x00, 0x62, 0x60, 0x4e,
2138 0xcb, 0xcf, 0x67, 0x60,
2139 0x06, 0x08, 0xa0, 0xa4,
2140 0xc4, 0x22, 0x80, 0x00,
2141 0x02, 0x00, 0x00, 0x00,
2144 const unsigned char kV3FrameData[] = {
2145 0x80, spdy_version_ch_, 0x00, 0x02,
2146 0x00, 0x00, 0x00, 0x31,
2147 0x00, 0x00, 0x00, 0x01,
2148 0x38, 0xea, 0xe3, 0xc6,
2149 0xa7, 0xc2, 0x02, 0xe5,
2150 0x0e, 0x50, 0xc2, 0x4b,
2151 0x4a, 0x04, 0xe5, 0x0b,
2152 0x66, 0x80, 0x00, 0x4a,
2153 0xcb, 0xcf, 0x07, 0x08,
2154 0x20, 0x10, 0x95, 0x96,
2155 0x9f, 0x0f, 0xa2, 0x00,
2156 0x02, 0x28, 0x29, 0xb1,
2157 0x08, 0x20, 0x80, 0x00,
2158 0x00, 0x00, 0x00, 0xff,
2161 const unsigned char kV4FrameData[] = {
2162 0x00, 0x35, 0x08, 0x00,
2163 0x00, 0x00, 0x00, 0x01,
2164 0x38, 0xea, 0xe3, 0xc6,
2165 0xa7, 0xc2, 0x02, 0xe5,
2166 0x0e, 0x50, 0xc2, 0x4b,
2167 0x4a, 0x04, 0xe5, 0x0b,
2168 0x66, 0x80, 0x00, 0x4a,
2169 0xcb, 0xcf, 0x07, 0x08,
2170 0x20, 0x10, 0x95, 0x96,
2171 0x9f, 0x0f, 0xa2, 0x00,
2172 0x02, 0x28, 0x29, 0xb1,
2173 0x08, 0x20, 0x80, 0x00,
2174 0x00, 0x00, 0x00, 0xff,
2177 SpdySynReplyIR syn_reply(1);
2178 syn_reply.SetHeader("bar", "foo");
2179 syn_reply.SetHeader("foo", "bar");
2180 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2182 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2183 } else if (IsSpdy3()) {
2184 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2186 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2190 #endif // !defined(USE_SYSTEM_ZLIB)
2192 TEST_P(SpdyFramerTest, CreateRstStream) {
2193 SpdyFramer framer(spdy_version_);
2196 const char kDescription[] = "RST_STREAM frame";
2197 const unsigned char kV3FrameData[] = { // Also applies for V2.
2198 0x80, spdy_version_ch_, 0x00, 0x03,
2199 0x00, 0x00, 0x00, 0x08,
2200 0x00, 0x00, 0x00, 0x01,
2201 0x00, 0x00, 0x00, 0x01,
2203 const unsigned char kV4FrameData[] = {
2204 0x00, 0x0f, 0x03, 0x00,
2205 0x00, 0x00, 0x00, 0x01,
2206 0x00, 0x00, 0x00, 0x01,
2209 const unsigned char kV4FrameDataOld[] = {
2210 0x00, 0x0c, 0x03, 0x00,
2211 0x00, 0x00, 0x00, 0x01,
2212 0x00, 0x00, 0x00, 0x01,
2214 net::SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2215 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2216 // TODO(jgraettinger): We expect to handle but not emit RST payloads.
2218 true /*!FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
2219 CompareFrame(kDescription, *frame, kV4FrameDataOld,
2220 arraysize(kV4FrameDataOld));
2221 } else if (IsSpdy4()) {
2222 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2224 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2229 const char kDescription[] = "RST_STREAM frame with max stream ID";
2230 const unsigned char kV3FrameData[] = { // Also applies for V2.
2231 0x80, spdy_version_ch_, 0x00, 0x03,
2232 0x00, 0x00, 0x00, 0x08,
2233 0x7f, 0xff, 0xff, 0xff,
2234 0x00, 0x00, 0x00, 0x01,
2236 const unsigned char kV4FrameData[] = {
2237 0x00, 0x0c, 0x03, 0x00,
2238 0x7f, 0xff, 0xff, 0xff,
2239 0x00, 0x00, 0x00, 0x01,
2241 net::SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2242 RST_STREAM_PROTOCOL_ERROR,
2244 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2246 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2248 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2253 const char kDescription[] = "RST_STREAM frame with max status code";
2254 const unsigned char kV3FrameData[] = { // Also applies for V2.
2255 0x80, spdy_version_ch_, 0x00, 0x03,
2256 0x00, 0x00, 0x00, 0x08,
2257 0x7f, 0xff, 0xff, 0xff,
2258 0x00, 0x00, 0x00, 0x06,
2260 const unsigned char kV4FrameData[] = {
2261 0x00, 0x0c, 0x03, 0x00,
2262 0x7f, 0xff, 0xff, 0xff,
2263 0x00, 0x00, 0x00, 0x06,
2265 net::SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2266 RST_STREAM_INTERNAL_ERROR,
2268 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2270 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2272 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2277 TEST_P(SpdyFramerTest, CreateSettings) {
2278 SpdyFramer framer(spdy_version_);
2281 const char kDescription[] = "Network byte order SETTINGS frame";
2283 uint32 kValue = 0x0a0b0c0d;
2284 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2285 SpdySettingsIds kId = static_cast<SpdySettingsIds>(0x020304);
2287 SettingsMap settings;
2288 settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
2290 EXPECT_EQ(kFlags, settings[kId].first);
2291 EXPECT_EQ(kValue, settings[kId].second);
2293 const unsigned char kV2FrameData[] = {
2294 0x80, spdy_version_ch_, 0x00, 0x04,
2295 0x00, 0x00, 0x00, 0x0c,
2296 0x00, 0x00, 0x00, 0x01,
2297 0x04, 0x03, 0x02, 0x01,
2298 0x0a, 0x0b, 0x0c, 0x0d,
2300 const unsigned char kV3FrameData[] = {
2301 0x80, spdy_version_ch_, 0x00, 0x04,
2302 0x00, 0x00, 0x00, 0x0c,
2303 0x00, 0x00, 0x00, 0x01,
2304 0x01, 0x02, 0x03, 0x04,
2305 0x0a, 0x0b, 0x0c, 0x0d,
2307 const unsigned char kV4FrameData[] = {
2308 0x00, 0x14, 0x04, 0x00,
2309 0x00, 0x00, 0x00, 0x00,
2310 0x00, 0x00, 0x00, 0x01,
2311 0x01, 0x02, 0x03, 0x04,
2312 0x0a, 0x0b, 0x0c, 0x0d,
2315 SpdySettingsIR settings_ir;
2316 settings_ir.AddSetting(kId,
2317 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2318 kFlags & SETTINGS_FLAG_PERSISTED,
2320 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2322 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2323 } else if (IsSpdy3()) {
2324 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2326 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2331 const char kDescription[] = "Basic SETTINGS frame";
2333 SettingsMap settings;
2334 AddSpdySettingFromWireFormat(
2335 &settings, 0x00000000, 0x00000001); // 1st Setting
2336 AddSpdySettingFromWireFormat(
2337 &settings, 0x01000001, 0x00000002); // 2nd Setting
2338 AddSpdySettingFromWireFormat(
2339 &settings, 0x02000002, 0x00000003); // 3rd Setting
2340 AddSpdySettingFromWireFormat(
2341 &settings, 0x03000003, 0xff000004); // 4th Setting
2343 const unsigned char kV3FrameData[] = { // Also applies for V2.
2344 0x80, spdy_version_ch_, 0x00, 0x04,
2345 0x00, 0x00, 0x00, 0x24,
2346 0x00, 0x00, 0x00, 0x04,
2347 0x00, 0x00, 0x00, 0x00, // 1st Setting
2348 0x00, 0x00, 0x00, 0x01,
2349 0x01, 0x00, 0x00, 0x01, // 2nd Setting
2350 0x00, 0x00, 0x00, 0x02,
2351 0x02, 0x00, 0x00, 0x02, // 3rd Setting
2352 0x00, 0x00, 0x00, 0x03,
2353 0x03, 0x00, 0x00, 0x03, // 4th Setting
2354 0xff, 0x00, 0x00, 0x04,
2356 const unsigned char kV4FrameData[] = {
2357 0x00, 0x2c, 0x04, 0x00,
2358 0x00, 0x00, 0x00, 0x00,
2359 0x00, 0x00, 0x00, 0x04,
2360 0x00, 0x00, 0x00, 0x00, // 1st Setting
2361 0x00, 0x00, 0x00, 0x01,
2362 0x01, 0x00, 0x00, 0x01, // 2nd Setting
2363 0x00, 0x00, 0x00, 0x02,
2364 0x02, 0x00, 0x00, 0x02, // 3rd Setting
2365 0x00, 0x00, 0x00, 0x03,
2366 0x03, 0x00, 0x00, 0x03, // 4th Setting
2367 0xff, 0x00, 0x00, 0x04,
2369 SpdySettingsIR settings_ir;
2370 for (SettingsMap::const_iterator it = settings.begin();
2371 it != settings.end();
2373 settings_ir.AddSetting(it->first,
2374 it->second.first & SETTINGS_FLAG_PLEASE_PERSIST,
2375 it->second.first & SETTINGS_FLAG_PERSISTED,
2378 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2380 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2382 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2387 const char kDescription[] = "Empty SETTINGS frame";
2389 const unsigned char kV3FrameData[] = { // Also applies for V2.
2390 0x80, spdy_version_ch_, 0x00, 0x04,
2391 0x00, 0x00, 0x00, 0x04,
2392 0x00, 0x00, 0x00, 0x00,
2394 const unsigned char kV4FrameData[] = {
2395 0x00, 0x0c, 0x04, 0x00,
2396 0x00, 0x00, 0x00, 0x00,
2397 0x00, 0x00, 0x00, 0x00,
2399 SpdySettingsIR settings_ir;
2400 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2402 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2404 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2409 TEST_P(SpdyFramerTest, CreatePingFrame) {
2410 SpdyFramer framer(spdy_version_);
2413 const char kDescription[] = "PING frame";
2414 const unsigned char kV3FrameData[] = { // Also applies for V2.
2415 0x80, spdy_version_ch_, 0x00, 0x06,
2416 0x00, 0x00, 0x00, 0x04,
2417 0x12, 0x34, 0x56, 0x78,
2419 const unsigned char kV4FrameData[] = {
2420 0x00, 0x0c, 0x06, 0x00,
2421 0x00, 0x00, 0x00, 0x00,
2422 0x12, 0x34, 0x56, 0x78,
2424 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(0x12345678u)));
2426 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2428 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2433 TEST_P(SpdyFramerTest, CreateGoAway) {
2434 SpdyFramer framer(spdy_version_);
2437 const char kDescription[] = "GOAWAY frame";
2438 const unsigned char kV2FrameData[] = {
2439 0x80, spdy_version_ch_, 0x00, 0x07,
2440 0x00, 0x00, 0x00, 0x04,
2441 0x00, 0x00, 0x00, 0x00, // Stream Id
2443 const unsigned char kV3FrameData[] = {
2444 0x80, spdy_version_ch_, 0x00, 0x07,
2445 0x00, 0x00, 0x00, 0x08,
2446 0x00, 0x00, 0x00, 0x00, // Stream Id
2447 0x00, 0x00, 0x00, 0x00, // Status
2449 const unsigned char kV4FrameData[] = {
2450 0x00, 0x12, 0x07, 0x00,
2451 0x00, 0x00, 0x00, 0x00,
2452 0x00, 0x00, 0x00, 0x00, // Stream id
2453 0x00, 0x00, 0x00, 0x00, // Status
2454 0x47, 0x41, // Opaque Description
2456 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2457 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2459 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2460 } else if (IsSpdy3()) {
2461 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2463 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2468 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2469 const unsigned char kV2FrameData[] = {
2470 0x80, spdy_version_ch_, 0x00, 0x07,
2471 0x00, 0x00, 0x00, 0x04,
2472 0x7f, 0xff, 0xff, 0xff, // Stream Id
2474 const unsigned char kV3FrameData[] = {
2475 0x80, spdy_version_ch_, 0x00, 0x07,
2476 0x00, 0x00, 0x00, 0x08,
2477 0x7f, 0xff, 0xff, 0xff, // Stream Id
2478 0x00, 0x00, 0x00, 0x02, // Status
2480 const unsigned char kV4FrameData[] = {
2481 0x00, 0x12, 0x07, 0x00,
2482 0x00, 0x00, 0x00, 0x00,
2483 0x7f, 0xff, 0xff, 0xff, // Stream Id
2484 0x00, 0x00, 0x00, 0x02, // Status
2485 0x47, 0x41, // Opaque Description
2487 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2488 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2490 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2491 } else if (IsSpdy3()) {
2492 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2494 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2499 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2500 SpdyFramer framer(spdy_version_);
2501 framer.set_enable_compression(false);
2504 const char kDescription[] = "HEADERS frame, no FIN";
2506 const unsigned char kV2FrameData[] = {
2507 0x80, spdy_version_ch_, 0x00, 0x08,
2508 0x00, 0x00, 0x00, 0x1C,
2509 0x00, 0x00, 0x00, 0x01,
2510 0x00, 0x00, 0x00, 0x02,
2511 0x00, 0x03, 'b', 'a',
2512 'r', 0x00, 0x03, 'f',
2513 'o', 'o', 0x00, 0x03,
2514 'f', 'o', 'o', 0x00,
2517 const unsigned char kV3FrameData[] = {
2518 0x80, spdy_version_ch_, 0x00, 0x08,
2519 0x00, 0x00, 0x00, 0x24,
2520 0x00, 0x00, 0x00, 0x01,
2521 0x00, 0x00, 0x00, 0x02,
2522 0x00, 0x00, 0x00, 0x03,
2523 'b', 'a', 'r', 0x00,
2524 0x00, 0x00, 0x03, 'f',
2525 'o', 'o', 0x00, 0x00,
2526 0x00, 0x03, 'f', 'o',
2527 'o', 0x00, 0x00, 0x00,
2530 const unsigned char kV4FrameData[] = {
2531 0x00, 0x28, 0x08, 0x00,
2532 0x00, 0x00, 0x00, 0x01,
2533 0x00, 0x00, 0x00, 0x02,
2534 0x00, 0x00, 0x00, 0x03,
2535 'b', 'a', 'r', 0x00,
2536 0x00, 0x00, 0x03, 'f',
2537 'o', 'o', 0x00, 0x00,
2538 0x00, 0x03, 'f', 'o',
2539 'o', 0x00, 0x00, 0x00,
2542 SpdyHeadersIR headers_ir(1);
2543 headers_ir.SetHeader("bar", "foo");
2544 headers_ir.SetHeader("foo", "bar");
2545 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2547 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2548 } else if (IsSpdy3()) {
2549 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2551 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2556 const char kDescription[] =
2557 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2559 const unsigned char kV2FrameData[] = {
2560 0x80, spdy_version_ch_, 0x00, 0x08,
2561 0x01, 0x00, 0x00, 0x19,
2562 0x7f, 0xff, 0xff, 0xff,
2563 0x00, 0x00, 0x00, 0x02,
2564 0x00, 0x00, 0x00, 0x03,
2565 'f', 'o', 'o', 0x00,
2566 0x03, 'f', 'o', 'o',
2567 0x00, 0x03, 'b', 'a',
2570 const unsigned char kV3FrameData[] = {
2571 0x80, spdy_version_ch_, 0x00, 0x08,
2572 0x01, 0x00, 0x00, 0x21,
2573 0x7f, 0xff, 0xff, 0xff,
2574 0x00, 0x00, 0x00, 0x02,
2575 0x00, 0x00, 0x00, 0x00,
2576 0x00, 0x00, 0x00, 0x03,
2577 'f', 'o', 'o', 0x00,
2578 0x00, 0x00, 0x03, 'f',
2579 'o', 'o', 0x00, 0x00,
2580 0x00, 0x03, 'b', 'a',
2583 const unsigned char kV4FrameData[] = {
2584 0x00, 0x25, 0x08, 0x01,
2585 0x7f, 0xff, 0xff, 0xff,
2586 0x00, 0x00, 0x00, 0x02,
2587 0x00, 0x00, 0x00, 0x00,
2588 0x00, 0x00, 0x00, 0x03,
2589 'f', 'o', 'o', 0x00,
2590 0x00, 0x00, 0x03, 'f',
2591 'o', 'o', 0x00, 0x00,
2592 0x00, 0x03, 'b', 'a',
2595 SpdyHeadersIR headers_ir(0x7fffffff);
2596 headers_ir.set_fin(true);
2597 headers_ir.SetHeader("", "foo");
2598 headers_ir.SetHeader("foo", "bar");
2599 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2601 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2602 } else if (IsSpdy3()) {
2603 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2605 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2610 const char kDescription[] =
2611 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2613 const unsigned char kV2FrameData[] = {
2614 0x80, spdy_version_ch_, 0x00, 0x08,
2615 0x01, 0x00, 0x00, 0x19,
2616 0x7f, 0xff, 0xff, 0xff,
2617 0x00, 0x00, 0x00, 0x02,
2618 0x00, 0x03, 'b', 'a',
2619 'r', 0x00, 0x03, 'f',
2620 'o', 'o', 0x00, 0x03,
2621 'f', 'o', 'o', 0x00,
2624 const unsigned char kV3FrameData[] = {
2625 0x80, spdy_version_ch_, 0x00, 0x08,
2626 0x01, 0x00, 0x00, 0x21,
2627 0x7f, 0xff, 0xff, 0xff,
2628 0x00, 0x00, 0x00, 0x02,
2629 0x00, 0x00, 0x00, 0x03,
2630 'b', 'a', 'r', 0x00,
2631 0x00, 0x00, 0x03, 'f',
2632 'o', 'o', 0x00, 0x00,
2633 0x00, 0x03, 'f', 'o',
2634 'o', 0x00, 0x00, 0x00,
2637 const unsigned char kV4FrameData[] = {
2638 0x00, 0x25, 0x08, 0x01,
2639 0x7f, 0xff, 0xff, 0xff,
2640 0x00, 0x00, 0x00, 0x02,
2641 0x00, 0x00, 0x00, 0x03,
2642 'b', 'a', 'r', 0x00,
2643 0x00, 0x00, 0x03, 'f',
2644 'o', 'o', 0x00, 0x00,
2645 0x00, 0x03, 'f', 'o',
2646 'o', 0x00, 0x00, 0x00,
2649 SpdyHeadersIR headers_ir(0x7fffffff);
2650 headers_ir.set_fin(true);
2651 headers_ir.SetHeader("bar", "foo");
2652 headers_ir.SetHeader("foo", "");
2653 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2655 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2656 } else if (IsSpdy3()) {
2657 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2659 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2664 // TODO(phajdan.jr): Clean up after we no longer need
2665 // to workaround http://crbug.com/139744.
2666 #if !defined(USE_SYSTEM_ZLIB)
2667 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2668 SpdyFramer framer(spdy_version_);
2669 framer.set_enable_compression(true);
2672 const char kDescription[] = "HEADERS frame, no FIN";
2674 const unsigned char kV2FrameData[] = {
2675 0x80, spdy_version_ch_, 0x00, 0x08,
2676 0x00, 0x00, 0x00, 0x32,
2677 0x00, 0x00, 0x00, 0x01,
2678 0x00, 0x00, 0x38, 0xea,
2679 0xdf, 0xa2, 0x51, 0xb2,
2680 0x62, 0x60, 0x62, 0x60,
2681 0x4e, 0x4a, 0x2c, 0x62,
2682 0x60, 0x06, 0x08, 0xa0,
2683 0xb4, 0xfc, 0x7c, 0x80,
2684 0x00, 0x62, 0x60, 0x4e,
2685 0xcb, 0xcf, 0x67, 0x60,
2686 0x06, 0x08, 0xa0, 0xa4,
2687 0xc4, 0x22, 0x80, 0x00,
2688 0x02, 0x00, 0x00, 0x00,
2691 const unsigned char kV3FrameData[] = {
2692 0x80, spdy_version_ch_, 0x00, 0x08,
2693 0x00, 0x00, 0x00, 0x31,
2694 0x00, 0x00, 0x00, 0x01,
2695 0x38, 0xea, 0xe3, 0xc6,
2696 0xa7, 0xc2, 0x02, 0xe5,
2697 0x0e, 0x50, 0xc2, 0x4b,
2698 0x4a, 0x04, 0xe5, 0x0b,
2699 0x66, 0x80, 0x00, 0x4a,
2700 0xcb, 0xcf, 0x07, 0x08,
2701 0x20, 0x10, 0x95, 0x96,
2702 0x9f, 0x0f, 0xa2, 0x00,
2703 0x02, 0x28, 0x29, 0xb1,
2704 0x08, 0x20, 0x80, 0x00,
2705 0x00, 0x00, 0x00, 0xff,
2708 const unsigned char kV4FrameData[] = {
2709 0x00, 0x35, 0x08, 0x00,
2710 0x00, 0x00, 0x00, 0x01,
2711 0x38, 0xea, 0xe3, 0xc6,
2712 0xa7, 0xc2, 0x02, 0xe5,
2713 0x0e, 0x50, 0xc2, 0x4b,
2714 0x4a, 0x04, 0xe5, 0x0b,
2715 0x66, 0x80, 0x00, 0x4a,
2716 0xcb, 0xcf, 0x07, 0x08,
2717 0x20, 0x10, 0x95, 0x96,
2718 0x9f, 0x0f, 0xa2, 0x00,
2719 0x02, 0x28, 0x29, 0xb1,
2720 0x08, 0x20, 0x80, 0x00,
2721 0x00, 0x00, 0x00, 0xff,
2724 SpdyHeadersIR headers_ir(1);
2725 headers_ir.SetHeader("bar", "foo");
2726 headers_ir.SetHeader("foo", "bar");
2727 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2729 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2730 } else if (IsSpdy3()) {
2731 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2733 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2737 #endif // !defined(USE_SYSTEM_ZLIB)
2739 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
2740 SpdyFramer framer(spdy_version_);
2743 const char kDescription[] = "WINDOW_UPDATE frame";
2744 const unsigned char kV3FrameData[] = { // Also applies for V2.
2745 0x80, spdy_version_ch_, 0x00, 0x09,
2746 0x00, 0x00, 0x00, 0x08,
2747 0x00, 0x00, 0x00, 0x01,
2748 0x00, 0x00, 0x00, 0x01,
2750 const unsigned char kV4FrameData[] = {
2751 0x00, 0x0c, 0x09, 0x00,
2752 0x00, 0x00, 0x00, 0x01,
2753 0x00, 0x00, 0x00, 0x01,
2755 scoped_ptr<SpdyFrame> frame(
2756 framer.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 1)));
2758 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2760 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2765 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
2766 const unsigned char kV3FrameData[] = { // Also applies for V2.
2767 0x80, spdy_version_ch_, 0x00, 0x09,
2768 0x00, 0x00, 0x00, 0x08,
2769 0x7f, 0xff, 0xff, 0xff,
2770 0x00, 0x00, 0x00, 0x01,
2772 const unsigned char kV4FrameData[] = {
2773 0x00, 0x0c, 0x09, 0x00,
2774 0x7f, 0xff, 0xff, 0xff,
2775 0x00, 0x00, 0x00, 0x01,
2777 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2778 net::SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2780 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2782 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2787 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
2788 const unsigned char kV3FrameData[] = { // Also applies for V2.
2789 0x80, spdy_version_ch_, 0x00, 0x09,
2790 0x00, 0x00, 0x00, 0x08,
2791 0x00, 0x00, 0x00, 0x01,
2792 0x7f, 0xff, 0xff, 0xff,
2794 const unsigned char kV4FrameData[] = {
2795 0x00, 0x0c, 0x09, 0x00,
2796 0x00, 0x00, 0x00, 0x01,
2797 0x7f, 0xff, 0xff, 0xff,
2799 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2800 net::SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2802 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2804 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2809 TEST_P(SpdyFramerTest, SerializeBlocked) {
2810 if (spdy_version_ < SPDY4) {
2814 SpdyFramer framer(spdy_version_);
2816 const char kDescription[] = "BLOCKED frame";
2817 const unsigned char kFrameData[] = {
2818 0x00, 0x08, 0x0b, 0x00,
2819 0x00, 0x00, 0x00, 0x00,
2821 SpdyBlockedIR blocked_ir(0);
2822 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
2823 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2826 TEST_P(SpdyFramerTest, CreateBlocked) {
2827 if (spdy_version_ < SPDY4) {
2831 SpdyFramer framer(spdy_version_);
2833 const char kDescription[] = "BLOCKED frame";
2834 const SpdyStreamId kStreamId = 3;
2836 scoped_ptr<SpdySerializedFrame> frame_serialized(
2837 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
2838 SpdyBlockedIR blocked_ir(kStreamId);
2839 scoped_ptr<SpdySerializedFrame> frame_created(
2840 framer.SerializeFrame(blocked_ir));
2842 CompareFrames(kDescription, *frame_serialized, *frame_created);
2845 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
2846 if (spdy_version_ < SPDY4) {
2850 SpdyFramer framer(spdy_version_);
2851 framer.set_enable_compression(false);
2853 const char kDescription[] = "PUSH_PROMISE frame";
2855 const unsigned char kFrameData[] = {
2856 0x00, 0x2C, 0x0C, 0x00, // length = 44, type = 12, flags = 0
2857 0x00, 0x00, 0x00, 0x2A, // stream id = 42
2858 0x00, 0x00, 0x00, 0x39, // promised stream id = 57
2859 0x00, 0x00, 0x00, 0x02, // start of uncompressed header block
2860 0x00, 0x00, 0x00, 0x03,
2861 'b', 'a', 'r', 0x00,
2862 0x00, 0x00, 0x03, 'f',
2863 'o', 'o', 0x00, 0x00,
2864 0x00, 0x03, 'f', 'o',
2865 'o', 0x00, 0x00, 0x00,
2866 0x03, 'b', 'a', 'r' // end of uncompressed header block
2869 SpdyPushPromiseIR push_promise(42, 57);
2870 push_promise.SetHeader("bar", "foo");
2871 push_promise.SetHeader("foo", "bar");
2872 scoped_ptr<SpdySerializedFrame> frame(
2873 framer.SerializePushPromise(push_promise));
2874 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2877 TEST_P(SpdyFramerTest, CreatePushPromiseCompressed) {
2878 if (spdy_version_ < SPDY4) {
2882 SpdyFramer framer(spdy_version_);
2883 framer.set_enable_compression(true);
2885 const char kDescription[] = "PUSH_PROMISE frame";
2887 const unsigned char kFrameData[] = {
2888 0x00, 0x39, 0x0C, 0x00, // length = 57, type = 12, flags = 0
2889 0x00, 0x00, 0x00, 0x2A, // stream id = 42
2890 0x00, 0x00, 0x00, 0x39, // promised stream id = 57
2891 0x38, 0xea, 0xe3, 0xc6, // start of compressed header block
2892 0xa7, 0xc2, 0x02, 0xe5,
2893 0x0e, 0x50, 0xc2, 0x4b,
2894 0x4a, 0x04, 0xe5, 0x0b,
2895 0x66, 0x80, 0x00, 0x4a,
2896 0xcb, 0xcf, 0x07, 0x08,
2897 0x20, 0x10, 0x95, 0x96,
2898 0x9f, 0x0f, 0xa2, 0x00,
2899 0x02, 0x28, 0x29, 0xb1,
2900 0x08, 0x20, 0x80, 0x00,
2901 0x00, 0x00, 0x00, 0xff,
2902 0xff // end of compressed header block
2905 SpdyPushPromiseIR push_promise(42, 57);
2906 push_promise.SetHeader("bar", "foo");
2907 push_promise.SetHeader("foo", "bar");
2908 scoped_ptr<SpdySerializedFrame> frame(
2909 framer.SerializePushPromise(push_promise));
2910 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2913 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
2914 SpdyFramer framer(spdy_version_);
2915 SpdySynStreamIR syn_stream(1);
2916 syn_stream.set_priority(1);
2917 syn_stream.SetHeader("aa", "vv");
2918 syn_stream.SetHeader("bb", "ww");
2919 SpdyHeaderBlock headers = syn_stream.name_value_block();
2920 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
2921 EXPECT_TRUE(control_frame.get() != NULL);
2922 TestSpdyVisitor visitor(spdy_version_);
2923 visitor.use_compression_ = true;
2924 visitor.SimulateInFramer(
2925 reinterpret_cast<unsigned char*>(control_frame->data()),
2926 control_frame->size());
2927 EXPECT_EQ(1, visitor.syn_frame_count_);
2928 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
2931 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
2932 SpdyFramer framer(spdy_version_);
2933 SpdySynReplyIR syn_reply(1);
2934 syn_reply.SetHeader("alpha", "beta");
2935 syn_reply.SetHeader("gamma", "delta");
2936 SpdyHeaderBlock headers = syn_reply.name_value_block();
2937 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
2938 EXPECT_TRUE(control_frame.get() != NULL);
2939 TestSpdyVisitor visitor(spdy_version_);
2940 visitor.use_compression_ = true;
2941 visitor.SimulateInFramer(
2942 reinterpret_cast<unsigned char*>(control_frame->data()),
2943 control_frame->size());
2945 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
2946 EXPECT_EQ(1, visitor.headers_frame_count_);
2948 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
2949 EXPECT_EQ(0, visitor.headers_frame_count_);
2951 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
2954 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
2955 SpdyFramer framer(spdy_version_);
2956 SpdyHeadersIR headers_ir(1);
2957 headers_ir.SetHeader("alpha", "beta");
2958 headers_ir.SetHeader("gamma", "delta");
2959 SpdyHeaderBlock headers = headers_ir.name_value_block();
2960 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
2961 EXPECT_TRUE(control_frame.get() != NULL);
2962 TestSpdyVisitor visitor(spdy_version_);
2963 visitor.use_compression_ = true;
2964 visitor.SimulateInFramer(
2965 reinterpret_cast<unsigned char*>(control_frame->data()),
2966 control_frame->size());
2967 EXPECT_EQ(1, visitor.headers_frame_count_);
2968 // control_frame_header_data_count_ depends on the random sequence
2969 // produced by rand(), so adding, removing or running single tests
2970 // alters this value. The best we can do is assert that it happens
2972 EXPECT_LE(2, visitor.control_frame_header_data_count_);
2973 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
2974 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
2975 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
2978 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
2979 SpdyFramer framer(spdy_version_);
2980 SpdyHeadersIR headers_ir(1);
2981 headers_ir.set_fin(true);
2982 headers_ir.SetHeader("alpha", "beta");
2983 headers_ir.SetHeader("gamma", "delta");
2984 SpdyHeaderBlock headers = headers_ir.name_value_block();
2985 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
2986 EXPECT_TRUE(control_frame.get() != NULL);
2987 TestSpdyVisitor visitor(spdy_version_);
2988 visitor.use_compression_ = true;
2989 visitor.SimulateInFramer(
2990 reinterpret_cast<unsigned char*>(control_frame->data()),
2991 control_frame->size());
2992 EXPECT_EQ(1, visitor.headers_frame_count_);
2993 // control_frame_header_data_count_ depends on the random sequence
2994 // produced by rand(), so adding, removing or running single tests
2995 // alters this value. The best we can do is assert that it happens
2997 EXPECT_LE(2, visitor.control_frame_header_data_count_);
2998 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
2999 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3000 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3003 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3004 // First find the size of the header value in order to just reach the control
3006 SpdyFramer framer(spdy_version_);
3007 framer.set_enable_compression(false);
3008 SpdySynStreamIR syn_stream(1);
3009 syn_stream.set_priority(1);
3010 syn_stream.SetHeader("aa", "");
3011 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3012 const size_t kBigValueSize =
3013 framer.GetControlFrameBufferMaxSize() - control_frame->size();
3015 // Create a frame at exatly that size.
3016 string big_value(kBigValueSize, 'x');
3017 syn_stream.SetHeader("aa", big_value.c_str());
3018 control_frame.reset(framer.SerializeSynStream(syn_stream));
3019 EXPECT_TRUE(control_frame.get() != NULL);
3020 EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size());
3022 TestSpdyVisitor visitor(spdy_version_);
3023 visitor.SimulateInFramer(
3024 reinterpret_cast<unsigned char*>(control_frame->data()),
3025 control_frame->size());
3026 EXPECT_TRUE(visitor.header_buffer_valid_);
3027 EXPECT_EQ(0, visitor.error_count_);
3028 EXPECT_EQ(1, visitor.syn_frame_count_);
3029 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3030 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3031 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3034 TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
3035 // First find the size of the header value in order to just reach the control
3037 SpdyFramer framer(spdy_version_);
3038 framer.set_enable_compression(false);
3039 SpdySynStreamIR syn_stream(1);
3040 syn_stream.SetHeader("aa", "");
3041 syn_stream.set_priority(1);
3042 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3043 const size_t kBigValueSize =
3044 framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1;
3046 // Create a frame at exatly that size.
3047 string big_value(kBigValueSize, 'x');
3048 syn_stream.SetHeader("aa", big_value.c_str());
3049 control_frame.reset(framer.SerializeSynStream(syn_stream));
3050 EXPECT_TRUE(control_frame.get() != NULL);
3051 EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1,
3052 control_frame->size());
3054 TestSpdyVisitor visitor(spdy_version_);
3055 visitor.SimulateInFramer(
3056 reinterpret_cast<unsigned char*>(control_frame->data()),
3057 control_frame->size());
3058 EXPECT_FALSE(visitor.header_buffer_valid_);
3059 EXPECT_EQ(1, visitor.error_count_);
3060 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3061 visitor.framer_.error_code())
3062 << SpdyFramer::ErrorCodeToString(framer.error_code());
3063 EXPECT_EQ(0, visitor.syn_frame_count_);
3064 EXPECT_EQ(0u, visitor.header_buffer_length_);
3067 // Check that the framer stops delivering header data chunks once the visitor
3068 // declares it doesn't want any more. This is important to guard against
3069 // "zip bomb" types of attacks.
3070 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3071 const size_t kHeaderBufferChunks = 4;
3072 const size_t kHeaderBufferSize =
3073 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3074 const size_t kBigValueSize = kHeaderBufferSize * 2;
3075 string big_value(kBigValueSize, 'x');
3076 SpdyFramer framer(spdy_version_);
3077 SpdySynStreamIR syn_stream(1);
3078 syn_stream.set_priority(1);
3079 syn_stream.set_fin(true);
3080 syn_stream.SetHeader("aa", big_value.c_str());
3081 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3082 EXPECT_TRUE(control_frame.get() != NULL);
3083 TestSpdyVisitor visitor(spdy_version_);
3084 visitor.set_header_buffer_size(kHeaderBufferSize);
3085 visitor.use_compression_ = true;
3086 visitor.SimulateInFramer(
3087 reinterpret_cast<unsigned char*>(control_frame->data()),
3088 control_frame->size());
3089 EXPECT_FALSE(visitor.header_buffer_valid_);
3090 EXPECT_EQ(1, visitor.error_count_);
3091 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3092 visitor.framer_.error_code())
3093 << SpdyFramer::ErrorCodeToString(framer.error_code());
3095 // The framer should have stoped delivering chunks after the visitor
3096 // signaled "stop" by returning false from OnControlFrameHeaderData().
3098 // control_frame_header_data_count_ depends on the random sequence
3099 // produced by rand(), so adding, removing or running single tests
3100 // alters this value. The best we can do is assert that it happens
3101 // at least kHeaderBufferChunks + 1.
3102 EXPECT_LE(kHeaderBufferChunks + 1,
3103 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3104 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3106 // The framer should not have sent half-close to the visitor.
3107 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3110 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3111 SpdyFramer framer(spdy_version_);
3112 framer.set_enable_compression(false);
3113 // Construct a SYN_STREAM control frame without compressing the header block,
3114 // and have the framer try to decompress it. This will cause the framer to
3115 // deal with a decompression error.
3116 SpdySynStreamIR syn_stream(1);
3117 syn_stream.set_priority(1);
3118 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3119 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3120 TestSpdyVisitor visitor(spdy_version_);
3121 visitor.use_compression_ = true;
3122 visitor.SimulateInFramer(
3123 reinterpret_cast<unsigned char*>(control_frame->data()),
3124 control_frame->size());
3125 EXPECT_EQ(1, visitor.error_count_);
3126 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3127 << SpdyFramer::ErrorCodeToString(framer.error_code());
3128 EXPECT_EQ(0u, visitor.header_buffer_length_);
3131 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3132 SpdyFramer framer(spdy_version_);
3133 // Create a GoAway frame that has a few extra bytes at the end.
3134 // We create enough overhead to overflow the framer's control frame buffer.
3135 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize);
3136 const unsigned char length = 1 + SpdyFramer::kControlFrameBufferSize;
3137 const unsigned char kV3FrameData[] = { // Also applies for V2.
3138 0x80, spdy_version_ch_, 0x00, 0x07,
3139 0x00, 0x00, 0x00, length,
3140 0x00, 0x00, 0x00, 0x00, // Stream ID
3141 0x00, 0x00, 0x00, 0x00, // Status
3144 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3145 // since it may carry opaque data. Verify that minimal length is tested.
3146 const unsigned char less_than_min_length = framer.GetGoAwayMinimumSize() - 1;
3147 const unsigned char kV4FrameData[] = {
3148 0x00, static_cast<uint8>(less_than_min_length), 0x07, 0x00,
3149 0x00, 0x00, 0x00, 0x00,
3150 0x00, 0x00, 0x00, 0x00, // Stream Id
3151 0x00, 0x00, 0x00, 0x00, // Status
3153 const size_t pad_length =
3154 length + framer.GetControlFrameHeaderSize() -
3155 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3156 string pad('A', pad_length);
3157 TestSpdyVisitor visitor(spdy_version_);
3160 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3162 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3164 visitor.SimulateInFramer(
3165 reinterpret_cast<const unsigned char*>(pad.c_str()),
3168 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3169 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3170 visitor.framer_.error_code())
3171 << SpdyFramer::ErrorCodeToString(framer.error_code());
3172 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3175 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3176 SpdyFramer framer(spdy_version_);
3177 SpdySettingsIR settings_ir;
3178 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3179 SetFrameLength(control_frame.get(), 0, spdy_version_);
3180 TestSpdyVisitor visitor(spdy_version_);
3181 visitor.use_compression_ = false;
3182 visitor.SimulateInFramer(
3183 reinterpret_cast<unsigned char*>(control_frame->data()),
3184 framer.GetControlFrameHeaderSize());
3185 // Should generate an error, since zero-len settings frames are unsupported.
3186 EXPECT_EQ(1, visitor.error_count_);
3189 // Tests handling of SETTINGS frames with invalid length.
3190 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3191 SpdyFramer framer(spdy_version_);
3192 SettingsMap settings;
3193 // Add a setting to pad the frame so that we don't get a buffer overflow when
3194 // calling SimulateInFramer() below.
3195 settings[SETTINGS_UPLOAD_BANDWIDTH] =
3196 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, 0x00000002);
3197 SpdySettingsIR settings_ir;
3198 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
3199 true, // please persist
3202 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3203 const size_t kNewLength = 5;
3204 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3205 TestSpdyVisitor visitor(spdy_version_);
3206 visitor.use_compression_ = false;
3207 visitor.SimulateInFramer(
3208 reinterpret_cast<unsigned char*>(control_frame->data()),
3209 framer.GetControlFrameHeaderSize() + kNewLength);
3210 // Should generate an error, since zero-len settings frames are unsupported.
3211 EXPECT_EQ(1, visitor.error_count_);
3214 // Tests handling of SETTINGS frames larger than the frame buffer size.
3215 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3216 SpdyFramer framer(spdy_version_);
3217 SettingsMap settings;
3218 SpdySettingsFlags flags = SETTINGS_FLAG_PLEASE_PERSIST;
3219 settings[SETTINGS_UPLOAD_BANDWIDTH] =
3220 SettingsFlagsAndValue(flags, 0x00000002);
3221 settings[SETTINGS_DOWNLOAD_BANDWIDTH] =
3222 SettingsFlagsAndValue(flags, 0x00000003);
3223 settings[SETTINGS_ROUND_TRIP_TIME] = SettingsFlagsAndValue(flags, 0x00000004);
3224 SpdySettingsIR settings_ir;
3225 for (SettingsMap::const_iterator it = settings.begin();
3226 it != settings.end();
3228 settings_ir.AddSetting(it->first,
3229 it->second.first & SETTINGS_FLAG_PLEASE_PERSIST,
3230 it->second.first & SETTINGS_FLAG_PERSISTED,
3233 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3234 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3235 control_frame->size());
3236 TestSpdyVisitor visitor(spdy_version_);
3237 visitor.use_compression_ = false;
3239 // Read all at once.
3240 visitor.SimulateInFramer(
3241 reinterpret_cast<unsigned char*>(control_frame->data()),
3242 control_frame->size());
3243 EXPECT_EQ(0, visitor.error_count_);
3244 EXPECT_EQ(settings.size(), static_cast<unsigned>(visitor.setting_count_));
3246 // Read data in small chunks.
3247 size_t framed_data = 0;
3248 size_t unframed_data = control_frame->size();
3249 size_t kReadChunkSize = 5; // Read five bytes at a time.
3250 while (unframed_data > 0) {
3251 size_t to_read = min(kReadChunkSize, unframed_data);
3252 visitor.SimulateInFramer(
3253 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3255 unframed_data -= to_read;
3256 framed_data += to_read;
3258 EXPECT_EQ(0, visitor.error_count_);
3259 EXPECT_EQ(settings.size() * 2, static_cast<unsigned>(visitor.setting_count_));
3262 // Tests handling of SETTINGS frame with duplicate entries.
3263 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3264 SpdyFramer framer(spdy_version_);
3266 const unsigned char kV2FrameData[] = {
3267 0x80, spdy_version_ch_, 0x00, 0x04,
3268 0x00, 0x00, 0x00, 0x1C,
3269 0x00, 0x00, 0x00, 0x03,
3270 0x01, 0x00, 0x00, 0x00, // 1st Setting
3271 0x00, 0x00, 0x00, 0x02,
3272 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3273 0x00, 0x00, 0x00, 0x03,
3274 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3275 0x00, 0x00, 0x00, 0x03,
3277 const unsigned char kV3FrameData[] = {
3278 0x80, spdy_version_ch_, 0x00, 0x04,
3279 0x00, 0x00, 0x00, 0x1C,
3280 0x00, 0x00, 0x00, 0x03,
3281 0x00, 0x00, 0x00, 0x01, // 1st Setting
3282 0x00, 0x00, 0x00, 0x02,
3283 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3284 0x00, 0x00, 0x00, 0x03,
3285 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3286 0x00, 0x00, 0x00, 0x03,
3288 const unsigned char kV4FrameData[] = {
3289 0x00, 0x24, 0x04, 0x00,
3290 0x00, 0x00, 0x00, 0x00,
3291 0x00, 0x00, 0x00, 0x03,
3292 0x00, 0x00, 0x00, 0x01, // 1st Setting
3293 0x00, 0x00, 0x00, 0x02,
3294 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3295 0x00, 0x00, 0x00, 0x03,
3296 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3297 0x00, 0x00, 0x00, 0x03,
3300 TestSpdyVisitor visitor(spdy_version_);
3301 visitor.use_compression_ = false;
3303 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3304 } else if (IsSpdy3()) {
3305 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3307 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3309 EXPECT_EQ(1, visitor.error_count_);
3310 EXPECT_EQ(1, visitor.setting_count_);
3313 // Tests handling of SETTINGS frame with entries out of order.
3314 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
3315 SpdyFramer framer(spdy_version_);
3317 const unsigned char kV2FrameData[] = {
3318 0x80, spdy_version_ch_, 0x00, 0x04,
3319 0x00, 0x00, 0x00, 0x1C,
3320 0x00, 0x00, 0x00, 0x03,
3321 0x02, 0x00, 0x00, 0x00, // 1st Setting
3322 0x00, 0x00, 0x00, 0x02,
3323 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
3324 0x00, 0x00, 0x00, 0x03,
3325 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3326 0x00, 0x00, 0x00, 0x03,
3328 const unsigned char kV3FrameData[] = {
3329 0x80, spdy_version_ch_, 0x00, 0x04,
3330 0x00, 0x00, 0x00, 0x1C,
3331 0x00, 0x00, 0x00, 0x03,
3332 0x00, 0x00, 0x00, 0x02, // 1st Setting
3333 0x00, 0x00, 0x00, 0x02,
3334 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3335 0x00, 0x00, 0x00, 0x03,
3336 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3337 0x00, 0x00, 0x00, 0x03,
3339 const unsigned char kV4FrameData[] = {
3340 0x00, 0x24, 0x04, 0x00,
3341 0x00, 0x00, 0x00, 0x00,
3342 0x00, 0x00, 0x00, 0x03,
3343 0x00, 0x00, 0x00, 0x02, // 1st Setting
3344 0x00, 0x00, 0x00, 0x02,
3345 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3346 0x00, 0x00, 0x00, 0x03,
3347 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3348 0x00, 0x00, 0x00, 0x03,
3351 TestSpdyVisitor visitor(spdy_version_);
3352 visitor.use_compression_ = false;
3354 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3355 } else if (IsSpdy3()) {
3356 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3358 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3360 EXPECT_EQ(1, visitor.error_count_);
3361 EXPECT_EQ(1, visitor.setting_count_);
3364 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
3365 SpdyFramer framer(spdy_version_);
3366 scoped_ptr<SpdyFrame> control_frame(
3367 framer.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 2)));
3368 TestSpdyVisitor visitor(spdy_version_);
3369 visitor.SimulateInFramer(
3370 reinterpret_cast<unsigned char*>(control_frame->data()),
3371 control_frame->size());
3372 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3373 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3376 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
3380 SpdyFramer framer(spdy_version_);
3381 const unsigned char kV3FrameData[] = { // Also applies for V2.
3382 0x80, spdy_version_ch_, 0x00, 0x0A,
3383 0x00, 0x00, 0x00, 0x33,
3384 0x00, 0x03, 0x00, 0x00,
3385 0x00, 0x05, 'p', 'r',
3386 'o', 'o', 'f', 0x00,
3387 0x00, 0x00, 0x06, 'a',
3389 't', 0x00, 0x00, 0x00,
3390 0x0C, 'a', 'n', 'o',
3393 't', 0x00, 0x00, 0x00,
3394 0x0A, 'f', 'i', 'n',
3398 TestSpdyVisitor visitor(spdy_version_);
3399 visitor.use_compression_ = false;
3400 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
3401 EXPECT_EQ(0, visitor.error_count_);
3404 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
3408 SpdyFramer framer(spdy_version_);
3409 const unsigned char kV3FrameData[] = { // Also applies for V2.
3410 0x80, spdy_version_ch_, 0x00, 0x0A,
3411 0x00, 0x00, 0x00, 0x33,
3412 0x00, 0x03, 0x00, 0x00,
3413 0x00, 0x05, 'p', 'r',
3414 'o', 'o', 'f', 0x00,
3415 0x00, 0x00, 0x06, 'a',
3417 't', 0x00, 0x00, 0x00,
3418 0x0C, 'a', 'n', 'o',
3421 't', 0x00, 0x00, 0x00,
3422 0x0A, 'f', 'i', 'n',
3426 TestSpdyVisitor visitor(spdy_version_);
3427 visitor.use_compression_ = false;
3428 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
3429 arraysize(kV3FrameData));
3430 scoped_ptr<SpdyFrame> control_frame(
3431 framer.SerializeWindowUpdate(net::SpdyWindowUpdateIR(1, 2)));
3432 multiple_frame_data.append(string(control_frame->data(),
3433 control_frame->size()));
3434 visitor.SimulateInFramer(
3435 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
3436 multiple_frame_data.length());
3437 EXPECT_EQ(0, visitor.error_count_);
3438 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3439 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3442 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
3443 if (spdy_version_ < 4) {
3447 SpdyFramer framer(spdy_version_);
3448 SpdyPushPromiseIR push_promise(42, 57);
3449 push_promise.SetHeader("foo", "bar");
3450 push_promise.SetHeader("bar", "foofoo");
3451 SpdyHeaderBlock headers = push_promise.name_value_block();
3452 scoped_ptr<SpdySerializedFrame> frame(
3453 framer.SerializePushPromise(push_promise));
3454 EXPECT_TRUE(frame.get() != NULL);
3455 TestSpdyVisitor visitor(spdy_version_);
3456 visitor.use_compression_ = true;
3457 visitor.SimulateInFramer(
3458 reinterpret_cast<unsigned char*>(frame->data()),
3460 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
3461 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
3462 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3465 TEST_P(SpdyFramerTest, ReadGarbage) {
3466 SpdyFramer framer(spdy_version_);
3467 unsigned char garbage_frame[256];
3468 memset(garbage_frame, ~0, sizeof(garbage_frame));
3469 TestSpdyVisitor visitor(spdy_version_);
3470 visitor.use_compression_ = false;
3471 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
3472 EXPECT_EQ(1, visitor.error_count_);
3475 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
3477 // Not valid for SPDY 4 since there is no version field.
3480 SpdyFramer framer(spdy_version_);
3481 const unsigned char kFrameData[] = {
3482 0x80, spdy_version_ch_, 0xff, 0xff,
3483 0xff, 0xff, 0xff, 0xff,
3485 TestSpdyVisitor visitor(spdy_version_);
3486 visitor.use_compression_ = false;
3487 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
3488 EXPECT_EQ(1, visitor.error_count_);
3491 TEST_P(SpdyFramerTest, SizesTest) {
3492 SpdyFramer framer(spdy_version_);
3493 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
3495 EXPECT_EQ(8u, framer.GetSynReplyMinimumSize());
3496 EXPECT_EQ(12u, framer.GetRstStreamMinimumSize());
3497 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
3498 EXPECT_EQ(12u, framer.GetPingSize());
3499 EXPECT_EQ(16u, framer.GetGoAwayMinimumSize());
3500 EXPECT_EQ(8u, framer.GetHeadersMinimumSize());
3501 EXPECT_EQ(12u, framer.GetWindowUpdateSize());
3502 EXPECT_EQ(8u, framer.GetBlockedSize());
3503 EXPECT_EQ(12u, framer.GetPushPromiseMinimumSize());
3504 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
3505 EXPECT_EQ(65535u, framer.GetFrameMaximumSize());
3506 EXPECT_EQ(65527u, framer.GetDataFrameMaximumPayload());
3508 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
3509 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
3510 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
3511 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
3512 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
3513 EXPECT_EQ(12u, framer.GetPingSize());
3514 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
3515 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
3516 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
3517 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
3518 EXPECT_EQ(16777215u, framer.GetFrameMaximumSize());
3519 EXPECT_EQ(16777207u, framer.GetDataFrameMaximumPayload());
3523 TEST_P(SpdyFramerTest, StateToStringTest) {
3524 EXPECT_STREQ("ERROR",
3525 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
3526 EXPECT_STREQ("AUTO_RESET",
3527 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
3528 EXPECT_STREQ("RESET",
3529 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
3530 EXPECT_STREQ("READING_COMMON_HEADER",
3531 SpdyFramer::StateToString(
3532 SpdyFramer::SPDY_READING_COMMON_HEADER));
3533 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
3534 SpdyFramer::StateToString(
3535 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
3536 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
3537 SpdyFramer::StateToString(
3538 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
3539 EXPECT_STREQ("FORWARD_STREAM_FRAME",
3540 SpdyFramer::StateToString(
3541 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
3542 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
3543 SpdyFramer::StateToString(
3544 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
3545 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
3546 SpdyFramer::StateToString(
3547 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
3548 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
3549 SpdyFramer::StateToString(
3550 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
3551 EXPECT_STREQ("UNKNOWN_STATE",
3552 SpdyFramer::StateToString(
3553 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1));
3556 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
3557 EXPECT_STREQ("NO_ERROR",
3558 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
3559 EXPECT_STREQ("INVALID_CONTROL_FRAME",
3560 SpdyFramer::ErrorCodeToString(
3561 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
3562 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
3563 SpdyFramer::ErrorCodeToString(
3564 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
3565 EXPECT_STREQ("ZLIB_INIT_FAILURE",
3566 SpdyFramer::ErrorCodeToString(
3567 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
3568 EXPECT_STREQ("UNSUPPORTED_VERSION",
3569 SpdyFramer::ErrorCodeToString(
3570 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
3571 EXPECT_STREQ("DECOMPRESS_FAILURE",
3572 SpdyFramer::ErrorCodeToString(
3573 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
3574 EXPECT_STREQ("COMPRESS_FAILURE",
3575 SpdyFramer::ErrorCodeToString(
3576 SpdyFramer::SPDY_COMPRESS_FAILURE));
3577 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
3578 SpdyFramer::ErrorCodeToString(
3579 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
3580 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
3581 SpdyFramer::ErrorCodeToString(
3582 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
3583 EXPECT_STREQ("UNKNOWN_ERROR",
3584 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
3587 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
3588 EXPECT_STREQ("INVALID",
3589 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
3590 EXPECT_STREQ("PROTOCOL_ERROR",
3591 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
3592 EXPECT_STREQ("INVALID_STREAM",
3593 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
3594 EXPECT_STREQ("REFUSED_STREAM",
3595 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
3596 EXPECT_STREQ("UNSUPPORTED_VERSION",
3597 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
3598 EXPECT_STREQ("CANCEL",
3599 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
3600 EXPECT_STREQ("INTERNAL_ERROR",
3601 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
3602 EXPECT_STREQ("FLOW_CONTROL_ERROR",
3603 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
3604 EXPECT_STREQ("UNKNOWN_STATUS",
3605 SpdyFramer::StatusCodeToString(RST_STREAM_NUM_STATUS_CODES));
3608 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
3609 EXPECT_STREQ("DATA",
3610 SpdyFramer::FrameTypeToString(DATA));
3611 EXPECT_STREQ("SYN_STREAM",
3612 SpdyFramer::FrameTypeToString(SYN_STREAM));
3613 EXPECT_STREQ("SYN_REPLY",
3614 SpdyFramer::FrameTypeToString(SYN_REPLY));
3615 EXPECT_STREQ("RST_STREAM",
3616 SpdyFramer::FrameTypeToString(RST_STREAM));
3617 EXPECT_STREQ("SETTINGS",
3618 SpdyFramer::FrameTypeToString(SETTINGS));
3619 EXPECT_STREQ("NOOP",
3620 SpdyFramer::FrameTypeToString(NOOP));
3621 EXPECT_STREQ("PING",
3622 SpdyFramer::FrameTypeToString(PING));
3623 EXPECT_STREQ("GOAWAY",
3624 SpdyFramer::FrameTypeToString(GOAWAY));
3625 EXPECT_STREQ("HEADERS",
3626 SpdyFramer::FrameTypeToString(HEADERS));
3627 EXPECT_STREQ("WINDOW_UPDATE",
3628 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
3629 EXPECT_STREQ("PUSH_PROMISE",
3630 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
3631 EXPECT_STREQ("CREDENTIAL",
3632 SpdyFramer::FrameTypeToString(CREDENTIAL));
3635 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
3637 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
3641 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3642 SpdyFramer framer(spdy_version_);
3643 framer.set_visitor(&visitor);
3645 EXPECT_CALL(visitor, OnError(_));
3646 framer.ProcessInput("HTTP/1.1", 8);
3647 EXPECT_TRUE(framer.probable_http_response());
3648 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3649 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
3650 << SpdyFramer::ErrorCodeToString(framer.error_code());
3653 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3654 SpdyFramer framer(spdy_version_);
3655 framer.set_visitor(&visitor);
3657 EXPECT_CALL(visitor, OnError(_));
3658 framer.ProcessInput("HTTP/1.0", 8);
3659 EXPECT_TRUE(framer.probable_http_response());
3660 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3661 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
3662 << SpdyFramer::ErrorCodeToString(framer.error_code());
3666 TEST_P(SpdyFramerTest, DataFrameFlags) {
3667 for (int flags = 0; flags < 256; ++flags) {
3668 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3670 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3671 SpdyFramer framer(spdy_version_);
3672 framer.set_visitor(&visitor);
3674 net::SpdyDataIR data_ir(1, StringPiece("hello", 5));
3675 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
3676 SetFrameFlags(frame.get(), flags, spdy_version_);
3678 if (flags & ~DATA_FLAG_FIN) {
3679 EXPECT_CALL(visitor, OnError(_));
3681 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
3682 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
3683 if (flags & DATA_FLAG_FIN) {
3684 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
3688 framer.ProcessInput(frame->data(), frame->size());
3689 if (flags & ~DATA_FLAG_FIN) {
3690 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3691 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
3692 framer.error_code())
3693 << SpdyFramer::ErrorCodeToString(framer.error_code());
3695 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3696 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3697 << SpdyFramer::ErrorCodeToString(framer.error_code());
3702 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
3703 for (int flags = 0; flags < 256; ++flags) {
3704 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3706 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3707 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
3708 SpdyFramer framer(spdy_version_);
3709 framer.set_visitor(&visitor);
3710 framer.set_debug_visitor(&debug_visitor);
3712 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
3714 SpdySynStreamIR syn_stream(8);
3715 syn_stream.set_associated_to_stream_id(3);
3716 syn_stream.set_priority(1);
3717 syn_stream.SetHeader("foo", "bar");
3718 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
3719 int set_flags = flags;
3721 // PRIORITY required for SYN_STREAM simulation.
3722 set_flags |= HEADERS_FLAG_PRIORITY;
3724 SetFrameFlags(frame.get(), set_flags, spdy_version_);
3727 flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
3728 EXPECT_CALL(visitor, OnError(_));
3729 } else if (IsSpdy4() &&
3730 flags & ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY)) {
3731 EXPECT_CALL(visitor, OnError(_));
3733 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
3735 EXPECT_CALL(visitor, OnSynStream(8, 0, 1, 0, flags & CONTROL_FLAG_FIN,
3738 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, 0, flags & CONTROL_FLAG_FIN,
3739 flags & CONTROL_FLAG_UNIDIRECTIONAL));
3741 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
3742 .WillRepeatedly(testing::Return(true));
3743 if (flags & DATA_FLAG_FIN) {
3744 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
3748 framer.ProcessInput(frame->data(), frame->size());
3750 flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
3751 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3752 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3753 framer.error_code())
3754 << SpdyFramer::ErrorCodeToString(framer.error_code());
3755 } else if (IsSpdy4() &&
3756 flags & ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY)) {
3757 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3758 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3759 framer.error_code())
3760 << SpdyFramer::ErrorCodeToString(framer.error_code());
3762 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3763 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3764 << SpdyFramer::ErrorCodeToString(framer.error_code());
3769 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
3771 // Covered by HEADERS case.
3774 for (int flags = 0; flags < 256; ++flags) {
3775 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3777 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3778 SpdyFramer framer(spdy_version_);
3779 framer.set_visitor(&visitor);
3781 SpdySynReplyIR syn_reply(37);
3782 syn_reply.SetHeader("foo", "bar");
3783 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
3784 SetFrameFlags(frame.get(), flags, spdy_version_);
3786 if (flags & ~CONTROL_FLAG_FIN) {
3787 EXPECT_CALL(visitor, OnError(_));
3789 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
3790 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
3791 .WillRepeatedly(testing::Return(true));
3792 if (flags & DATA_FLAG_FIN) {
3793 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
3797 framer.ProcessInput(frame->data(), frame->size());
3798 if (flags & ~CONTROL_FLAG_FIN) {
3799 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3800 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3801 framer.error_code())
3802 << SpdyFramer::ErrorCodeToString(framer.error_code());
3804 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3805 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3806 << SpdyFramer::ErrorCodeToString(framer.error_code());
3811 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
3812 for (int flags = 0; flags < 256; ++flags) {
3813 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3815 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3816 SpdyFramer framer(spdy_version_);
3817 framer.set_visitor(&visitor);
3819 net::SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
3820 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
3821 SetFrameFlags(frame.get(), flags, spdy_version_);
3824 EXPECT_CALL(visitor, OnError(_));
3826 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
3829 framer.ProcessInput(frame->data(), frame->size());
3831 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3832 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3833 framer.error_code())
3834 << SpdyFramer::ErrorCodeToString(framer.error_code());
3836 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3837 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3838 << SpdyFramer::ErrorCodeToString(framer.error_code());
3843 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
3844 for (int flags = 0; flags < 256; ++flags) {
3845 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3847 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3848 SpdyFramer framer(spdy_version_);
3849 framer.set_visitor(&visitor);
3851 SpdySettingsIR settings_ir;
3852 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
3856 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
3857 SetFrameFlags(frame.get(), flags, spdy_version_);
3859 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
3860 EXPECT_CALL(visitor, OnError(_));
3862 EXPECT_CALL(visitor, OnSettings(
3863 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
3864 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
3865 SETTINGS_FLAG_NONE, 54321));
3868 framer.ProcessInput(frame->data(), frame->size());
3869 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
3870 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3871 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3872 framer.error_code())
3873 << SpdyFramer::ErrorCodeToString(framer.error_code());
3875 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3876 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3877 << SpdyFramer::ErrorCodeToString(framer.error_code());
3882 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
3883 for (int flags = 0; flags < 256; ++flags) {
3884 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3886 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3887 SpdyFramer framer(spdy_version_);
3888 framer.set_visitor(&visitor);
3890 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
3891 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
3892 SetFrameFlags(frame.get(), flags, spdy_version_);
3895 EXPECT_CALL(visitor, OnError(_));
3897 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
3900 framer.ProcessInput(frame->data(), frame->size());
3902 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3903 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3904 framer.error_code())
3905 << SpdyFramer::ErrorCodeToString(framer.error_code());
3907 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3908 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3909 << SpdyFramer::ErrorCodeToString(framer.error_code());
3914 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
3915 for (int flags = 0; flags < 256; ++flags) {
3916 if (IsSpdy4() && flags & HEADERS_FLAG_PRIORITY) {
3917 // Covered by SYN_STREAM case.
3920 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3922 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3923 SpdyFramer framer(spdy_version_);
3924 framer.set_visitor(&visitor);
3926 SpdyHeadersIR headers_ir(57);
3927 headers_ir.SetHeader("foo", "bar");
3928 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3929 SetFrameFlags(frame.get(), flags, spdy_version_);
3931 if (flags & ~CONTROL_FLAG_FIN) {
3932 EXPECT_CALL(visitor, OnError(_));
3934 EXPECT_CALL(visitor, OnHeaders(57, flags & CONTROL_FLAG_FIN));
3935 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
3936 .WillRepeatedly(testing::Return(true));
3937 if (flags & DATA_FLAG_FIN) {
3938 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
3942 framer.ProcessInput(frame->data(), frame->size());
3943 if (flags & ~CONTROL_FLAG_FIN) {
3944 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3945 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3946 framer.error_code())
3947 << SpdyFramer::ErrorCodeToString(framer.error_code());
3949 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3950 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3951 << SpdyFramer::ErrorCodeToString(framer.error_code());
3956 TEST_P(SpdyFramerTest, PingFrameFlags) {
3957 for (int flags = 0; flags < 256; ++flags) {
3958 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3960 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3961 SpdyFramer framer(spdy_version_);
3962 framer.set_visitor(&visitor);
3964 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
3965 SetFrameFlags(frame.get(), flags, spdy_version_);
3968 EXPECT_CALL(visitor, OnError(_));
3970 EXPECT_CALL(visitor, OnPing(42));
3973 framer.ProcessInput(frame->data(), frame->size());
3975 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3976 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
3977 framer.error_code())
3978 << SpdyFramer::ErrorCodeToString(framer.error_code());
3980 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
3981 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
3982 << SpdyFramer::ErrorCodeToString(framer.error_code());
3987 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
3988 for (int flags = 0; flags < 256; ++flags) {
3989 SCOPED_TRACE(testing::Message() << "Flags " << flags);
3991 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3992 SpdyFramer framer(spdy_version_);
3993 framer.set_visitor(&visitor);
3995 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3996 net::SpdyWindowUpdateIR(4, 1024)));
3997 SetFrameFlags(frame.get(), flags, spdy_version_);
4000 EXPECT_CALL(visitor, OnError(_));
4002 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
4005 framer.ProcessInput(frame->data(), frame->size());
4007 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4008 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4009 framer.error_code())
4010 << SpdyFramer::ErrorCodeToString(framer.error_code());
4012 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4013 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4014 << SpdyFramer::ErrorCodeToString(framer.error_code());
4019 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
4020 if (spdy_version_ < SPDY4) {
4024 for (int flags = 0; flags < 256; ++flags) {
4025 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4027 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
4028 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
4029 SpdyFramer framer(spdy_version_);
4030 framer.set_visitor(&visitor);
4031 framer.set_debug_visitor(&debug_visitor);
4033 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
4035 SpdyPushPromiseIR push_promise(42, 57);
4036 push_promise.SetHeader("foo", "bar");
4037 scoped_ptr<SpdySerializedFrame> frame(
4038 framer.SerializePushPromise(push_promise));
4039 SetFrameFlags(frame.get(), flags, spdy_version_);
4042 EXPECT_CALL(visitor, OnError(_));
4044 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
4045 EXPECT_CALL(visitor, OnPushPromise(42, 57));
4046 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
4047 .WillRepeatedly(testing::Return(true));
4050 framer.ProcessInput(frame->data(), frame->size());
4052 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4053 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4054 framer.error_code())
4055 << SpdyFramer::ErrorCodeToString(framer.error_code());
4057 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4058 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4059 << SpdyFramer::ErrorCodeToString(framer.error_code());
4064 TEST_P(SpdyFramerTest, EmptySynStream) {
4065 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4066 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4067 SpdyFramer framer(spdy_version_);
4068 framer.set_visitor(&visitor);
4069 framer.set_debug_visitor(&debug_visitor);
4071 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
4073 SpdySynStreamIR syn_stream(1);
4074 syn_stream.set_priority(1);
4075 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4076 // Adjust size to remove the name/value block.
4080 framer.GetSynStreamMinimumSize(),
4085 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
4089 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
4090 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, 0, false, false));
4091 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
4093 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
4094 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4095 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4096 << SpdyFramer::ErrorCodeToString(framer.error_code());
4099 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
4100 const uint32 kId = 0x020304;
4101 const uint32 kFlags = 0x01;
4102 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
4104 SettingsFlagsAndId id_and_flags =
4105 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
4106 EXPECT_EQ(kId, id_and_flags.id());
4107 EXPECT_EQ(kFlags, id_and_flags.flags());
4108 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
4111 // Test handling of a RST_STREAM with out-of-bounds status codes.
4112 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
4113 DCHECK_GE(0xff, RST_STREAM_NUM_STATUS_CODES);
4115 const unsigned char kV3RstStreamInvalid[] = {
4116 0x80, spdy_version_ch_, 0x00, 0x03,
4117 0x00, 0x00, 0x00, 0x08,
4118 0x00, 0x00, 0x00, 0x01,
4119 0x00, 0x00, 0x00, RST_STREAM_INVALID
4121 const unsigned char kV4RstStreamInvalid[] = {
4122 0x00, 0x0c, 0x03, 0x00,
4123 0x00, 0x00, 0x00, 0x01,
4124 0x00, 0x00, 0x00, RST_STREAM_INVALID
4127 const unsigned char kV3RstStreamNumStatusCodes[] = {
4128 0x80, spdy_version_ch_, 0x00, 0x03,
4129 0x00, 0x00, 0x00, 0x08,
4130 0x00, 0x00, 0x00, 0x01,
4131 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES
4133 const unsigned char kV4RstStreamNumStatusCodes[] = {
4134 0x00, 0x0c, 0x03, 0x00,
4135 0x00, 0x00, 0x00, 0x01,
4136 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES
4139 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4140 SpdyFramer framer(spdy_version_);
4141 framer.set_visitor(&visitor);
4143 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
4145 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
4146 arraysize(kV4RstStreamInvalid));
4148 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
4149 arraysize(kV3RstStreamInvalid));
4151 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4152 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4153 << SpdyFramer::ErrorCodeToString(framer.error_code());
4155 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
4157 framer.ProcessInput(
4158 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
4159 arraysize(kV4RstStreamNumStatusCodes));
4161 framer.ProcessInput(
4162 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
4163 arraysize(kV3RstStreamNumStatusCodes));
4165 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4166 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4167 << SpdyFramer::ErrorCodeToString(framer.error_code());
4170 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
4171 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
4172 const unsigned char kV2FrameData[] = {
4173 0x80, spdy_version_ch_, 0x00, 0x07,
4174 0x00, 0x00, 0x00, 0x04,
4175 0xff, 0xff, 0xff, 0xff,
4177 const unsigned char kV3FrameData[] = {
4178 0x80, spdy_version_ch_, 0x00, 0x07,
4179 0x00, 0x00, 0x00, 0x08,
4180 0xff, 0xff, 0xff, 0xff,
4181 0x00, 0x00, 0x00, 0x00,
4183 const unsigned char kV4FrameData[] = {
4184 0x00, 0x10, 0x07, 0x00,
4185 0x00, 0x00, 0x00, 0x00,
4186 0xff, 0xff, 0xff, 0xff,
4187 0x00, 0x00, 0x00, 0x00,
4190 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4191 SpdyFramer framer(spdy_version_);
4192 framer.set_visitor(&visitor);
4194 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
4196 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
4197 arraysize(kV2FrameData));
4198 } else if (IsSpdy3()) {
4199 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
4200 arraysize(kV3FrameData));
4202 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
4203 arraysize(kV4FrameData));
4205 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4206 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4207 << SpdyFramer::ErrorCodeToString(framer.error_code());
4210 TEST_P(SpdyFramerTest, OnBlocked) {
4211 if (spdy_version_ < SPDY4) {
4215 const SpdyStreamId kStreamId = 0;
4217 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4218 SpdyFramer framer(spdy_version_);
4219 framer.set_visitor(&visitor);
4221 EXPECT_CALL(visitor, OnBlocked(kStreamId));
4223 SpdyBlockedIR blocked_ir(0);
4224 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
4225 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
4227 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4228 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4229 << SpdyFramer::ErrorCodeToString(framer.error_code());