Cast: Fix rtcp event dedup logic in rtcp_receiver.
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob8542835b67fdc00e256998568be205f6c14f5de7
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.
5 #include <algorithm>
6 #include <iostream>
7 #include <limits>
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
21 using base::StringPiece;
22 using std::string;
23 using std::max;
24 using std::min;
25 using std::numeric_limits;
26 using testing::ElementsAre;
27 using testing::Pair;
28 using testing::_;
30 namespace net {
32 namespace test {
34 static const size_t kMaxDecompressedSize = 1024;
36 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
37 public:
38 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
39 SpdyFrameType type,
40 size_t payload_len,
41 size_t frame_len));
43 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
44 SpdyFrameType type,
45 size_t frame_len));
48 class SpdyFramerTestUtil {
49 public:
50 // Decompress a single frame using the decompression context held by
51 // the SpdyFramer. The implemention is meant for use only in tests
52 // and will CHECK fail if the input is anything other than a single,
53 // well-formed compressed frame.
55 // Returns a new decompressed SpdyFrame.
56 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
57 SpdyFramer* framer, const SpdyFrameType& frame) {
58 DecompressionVisitor visitor(framer->protocol_version());
59 framer->set_visitor(&visitor);
60 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
61 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
62 framer->set_visitor(NULL);
64 char* buffer = visitor.ReleaseBuffer();
65 CHECK(buffer != NULL);
66 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
67 SetFrameLength(decompressed_frame,
68 visitor.size() - framer->GetControlFrameHeaderSize(),
69 framer->protocol_version());
70 return decompressed_frame;
73 class DecompressionVisitor : public SpdyFramerVisitorInterface {
74 public:
75 explicit DecompressionVisitor(SpdyMajorVersion version)
76 : version_(version), size_(0), finished_(false) {}
78 void ResetBuffer() {
79 CHECK(buffer_.get() == NULL);
80 CHECK_EQ(0u, size_);
81 CHECK(!finished_);
82 buffer_.reset(new char[kMaxDecompressedSize]);
85 virtual void OnError(SpdyFramer* framer) OVERRIDE { LOG(FATAL); }
86 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
87 size_t length,
88 bool fin) OVERRIDE {
89 LOG(FATAL) << "Unexpected data frame header";
91 virtual void OnStreamFrameData(SpdyStreamId stream_id,
92 const char* data,
93 size_t len,
94 bool fin) OVERRIDE {
95 LOG(FATAL);
98 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
99 const char* header_data,
100 size_t len) OVERRIDE {
101 CHECK(buffer_.get() != NULL);
102 CHECK_GE(kMaxDecompressedSize, size_ + len);
103 CHECK(!finished_);
104 if (len != 0) {
105 memcpy(buffer_.get() + size_, header_data, len);
106 size_ += len;
107 } else {
108 // Done.
109 finished_ = true;
111 return true;
114 virtual void OnSynStream(SpdyStreamId stream_id,
115 SpdyStreamId associated_stream_id,
116 SpdyPriority priority,
117 bool fin,
118 bool unidirectional) OVERRIDE {
119 SpdyFramer framer(version_);
120 framer.set_enable_compression(false);
121 SpdySynStreamIR syn_stream(stream_id);
122 syn_stream.set_associated_to_stream_id(associated_stream_id);
123 syn_stream.set_priority(priority);
124 syn_stream.set_fin(fin);
125 syn_stream.set_unidirectional(unidirectional);
126 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
127 ResetBuffer();
128 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
129 size_ += framer.GetSynStreamMinimumSize();
132 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
133 SpdyFramer framer(version_);
134 framer.set_enable_compression(false);
135 SpdyHeadersIR headers(stream_id);
136 headers.set_fin(fin);
137 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
138 ResetBuffer();
139 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
140 size_ += framer.GetSynStreamMinimumSize();
143 virtual void OnRstStream(SpdyStreamId stream_id,
144 SpdyRstStreamStatus status) OVERRIDE {
145 LOG(FATAL);
147 virtual void OnSetting(SpdySettingsIds id,
148 uint8 flags,
149 uint32 value) OVERRIDE {
150 LOG(FATAL);
152 virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
153 LOG(FATAL);
155 virtual void OnSettingsEnd() OVERRIDE { LOG(FATAL); }
156 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
157 SpdyGoAwayStatus status) OVERRIDE {
158 LOG(FATAL);
161 virtual void OnHeaders(SpdyStreamId stream_id,
162 bool fin,
163 bool end) OVERRIDE {
164 SpdyFramer framer(version_);
165 framer.set_enable_compression(false);
166 SpdyHeadersIR headers(stream_id);
167 headers.set_fin(fin);
168 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
169 ResetBuffer();
170 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
171 size_ += framer.GetHeadersMinimumSize();
174 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
175 LOG(FATAL);
178 virtual void OnPushPromise(SpdyStreamId stream_id,
179 SpdyStreamId promised_stream_id,
180 bool end) 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));
185 ResetBuffer();
186 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
187 size_ += framer.GetPushPromiseMinimumSize();
190 virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
191 LOG(FATAL);
194 char* ReleaseBuffer() {
195 CHECK(finished_);
196 return buffer_.release();
199 virtual void OnWindowUpdate(SpdyStreamId stream_id,
200 uint32 delta_window_size) OVERRIDE {
201 LOG(FATAL);
204 size_t size() const {
205 CHECK(finished_);
206 return size_;
209 private:
210 SpdyMajorVersion version_;
211 scoped_ptr<char[]> buffer_;
212 size_t size_;
213 bool finished_;
215 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
218 private:
219 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
222 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
223 public SpdyFramerDebugVisitorInterface {
224 public:
225 // This is larger than our max frame size because header blocks that
226 // are too long can spill over into CONTINUATION frames.
227 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
229 explicit TestSpdyVisitor(SpdyMajorVersion version)
230 : framer_(version),
231 use_compression_(false),
232 error_count_(0),
233 syn_frame_count_(0),
234 syn_reply_frame_count_(0),
235 headers_frame_count_(0),
236 push_promise_frame_count_(0),
237 goaway_count_(0),
238 setting_count_(0),
239 settings_ack_sent_(0),
240 settings_ack_received_(0),
241 continuation_count_(0),
242 last_window_update_stream_(0),
243 last_window_update_delta_(0),
244 last_push_promise_stream_(0),
245 last_push_promise_promised_stream_(0),
246 data_bytes_(0),
247 fin_frame_count_(0),
248 fin_opaque_data_(),
249 fin_flag_count_(0),
250 zero_length_data_frame_count_(0),
251 control_frame_header_data_count_(0),
252 zero_length_control_frame_header_data_count_(0),
253 data_frame_count_(0),
254 last_payload_len_(0),
255 last_frame_len_(0),
256 header_buffer_(new char[kDefaultHeaderBufferSize]),
257 header_buffer_length_(0),
258 header_buffer_size_(kDefaultHeaderBufferSize),
259 header_stream_id_(-1),
260 header_control_type_(DATA),
261 header_buffer_valid_(false) {
264 virtual void OnError(SpdyFramer* f) OVERRIDE {
265 LOG(INFO) << "SpdyFramer Error: "
266 << SpdyFramer::ErrorCodeToString(f->error_code());
267 ++error_count_;
270 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
271 size_t length,
272 bool fin) OVERRIDE {
273 ++data_frame_count_;
274 header_stream_id_ = stream_id;
277 virtual void OnStreamFrameData(SpdyStreamId stream_id,
278 const char* data,
279 size_t len,
280 bool fin) OVERRIDE {
281 EXPECT_EQ(header_stream_id_, stream_id);
282 if (len == 0)
283 ++zero_length_data_frame_count_;
285 data_bytes_ += len;
286 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
287 if (len > 0) {
288 for (size_t i = 0 ; i < len; ++i) {
289 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
292 std::cerr << "\", " << len << ")\n";
295 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
296 const char* header_data,
297 size_t len) OVERRIDE {
298 ++control_frame_header_data_count_;
299 CHECK_EQ(header_stream_id_, stream_id);
300 if (len == 0) {
301 ++zero_length_control_frame_header_data_count_;
302 // Indicates end-of-header-block.
303 headers_.clear();
304 CHECK(header_buffer_valid_);
305 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
306 header_buffer_.get(), header_buffer_length_, &headers_);
307 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
308 << "Check failed: header_buffer_length_ == parsed_length "
309 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
310 return true;
312 const size_t available = header_buffer_size_ - header_buffer_length_;
313 if (len > available) {
314 header_buffer_valid_ = false;
315 return false;
317 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
318 header_buffer_length_ += len;
319 return true;
322 virtual void OnSynStream(SpdyStreamId stream_id,
323 SpdyStreamId associated_stream_id,
324 SpdyPriority priority,
325 bool fin,
326 bool unidirectional) OVERRIDE {
327 ++syn_frame_count_;
328 InitHeaderStreaming(SYN_STREAM, stream_id);
329 if (fin) {
330 ++fin_flag_count_;
334 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
335 ++syn_reply_frame_count_;
336 InitHeaderStreaming(SYN_REPLY, stream_id);
337 if (fin) {
338 ++fin_flag_count_;
342 virtual void OnRstStream(SpdyStreamId stream_id,
343 SpdyRstStreamStatus status) OVERRIDE {
344 ++fin_frame_count_;
347 virtual bool OnRstStreamFrameData(const char* rst_stream_data,
348 size_t len) OVERRIDE {
349 if ((rst_stream_data != NULL) && (len > 0)) {
350 fin_opaque_data_ += std::string(rst_stream_data, len);
352 return true;
355 virtual void OnSetting(SpdySettingsIds id,
356 uint8 flags,
357 uint32 value) OVERRIDE {
358 ++setting_count_;
361 virtual void OnSettingsAck() OVERRIDE {
362 DCHECK_LT(SPDY3, framer_.protocol_version());
363 ++settings_ack_received_;
366 virtual void OnSettingsEnd() OVERRIDE {
367 if (framer_.protocol_version() <= SPDY3) { return; }
368 ++settings_ack_sent_;
371 virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
372 DLOG(FATAL);
375 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
376 SpdyGoAwayStatus status) OVERRIDE {
377 ++goaway_count_;
380 virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE {
381 ++headers_frame_count_;
382 InitHeaderStreaming(HEADERS, stream_id);
383 if (fin) {
384 ++fin_flag_count_;
388 virtual void OnWindowUpdate(SpdyStreamId stream_id,
389 uint32 delta_window_size) OVERRIDE {
390 last_window_update_stream_ = stream_id;
391 last_window_update_delta_ = delta_window_size;
394 virtual void OnPushPromise(SpdyStreamId stream_id,
395 SpdyStreamId promised_stream_id,
396 bool end) OVERRIDE {
397 ++push_promise_frame_count_;
398 InitHeaderStreaming(PUSH_PROMISE, stream_id);
399 last_push_promise_stream_ = stream_id;
400 last_push_promise_promised_stream_ = promised_stream_id;
403 virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
404 ++continuation_count_;
407 virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
408 SpdyFrameType type,
409 size_t payload_len,
410 size_t frame_len) OVERRIDE {
411 last_payload_len_ = payload_len;
412 last_frame_len_ = frame_len;
415 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
416 SpdyFrameType type,
417 size_t frame_len) OVERRIDE {
418 last_frame_len_ = frame_len;
421 // Convenience function which runs a framer simulation with particular input.
422 void SimulateInFramer(const unsigned char* input, size_t size) {
423 framer_.set_enable_compression(use_compression_);
424 framer_.set_visitor(this);
425 size_t input_remaining = size;
426 const char* input_ptr = reinterpret_cast<const char*>(input);
427 while (input_remaining > 0 &&
428 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
429 // To make the tests more interesting, we feed random (amd small) chunks
430 // into the framer. This simulates getting strange-sized reads from
431 // the socket.
432 const size_t kMaxReadSize = 32;
433 size_t bytes_read =
434 (rand() % min(input_remaining, kMaxReadSize)) + 1;
435 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
436 input_remaining -= bytes_processed;
437 input_ptr += bytes_processed;
441 void InitHeaderStreaming(SpdyFrameType header_control_type,
442 SpdyStreamId stream_id) {
443 DCHECK_GE(header_control_type, FIRST_CONTROL_TYPE);
444 DCHECK_LE(header_control_type, LAST_CONTROL_TYPE);
445 memset(header_buffer_.get(), 0, header_buffer_size_);
446 header_buffer_length_ = 0;
447 header_stream_id_ = stream_id;
448 header_control_type_ = header_control_type;
449 header_buffer_valid_ = true;
450 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
453 // Override the default buffer size (16K). Call before using the framer!
454 void set_header_buffer_size(size_t header_buffer_size) {
455 header_buffer_size_ = header_buffer_size;
456 header_buffer_.reset(new char[header_buffer_size]);
459 static size_t header_data_chunk_max_size() {
460 return SpdyFramer::kHeaderDataChunkMaxSize;
463 SpdyFramer framer_;
464 bool use_compression_;
466 // Counters from the visitor callbacks.
467 int error_count_;
468 int syn_frame_count_;
469 int syn_reply_frame_count_;
470 int headers_frame_count_;
471 int push_promise_frame_count_;
472 int goaway_count_;
473 int setting_count_;
474 int settings_ack_sent_;
475 int settings_ack_received_;
476 int continuation_count_;
477 SpdyStreamId last_window_update_stream_;
478 uint32 last_window_update_delta_;
479 SpdyStreamId last_push_promise_stream_;
480 SpdyStreamId last_push_promise_promised_stream_;
481 int data_bytes_;
482 int fin_frame_count_; // The count of RST_STREAM type frames received.
483 std::string fin_opaque_data_;
484 int fin_flag_count_; // The count of frames with the FIN flag set.
485 int zero_length_data_frame_count_; // The count of zero-length data frames.
486 int control_frame_header_data_count_; // The count of chunks received.
487 // The count of zero-length control frame header data chunks received.
488 int zero_length_control_frame_header_data_count_;
489 int data_frame_count_;
490 size_t last_payload_len_;
491 size_t last_frame_len_;
493 // Header block streaming state:
494 scoped_ptr<char[]> header_buffer_;
495 size_t header_buffer_length_;
496 size_t header_buffer_size_;
497 SpdyStreamId header_stream_id_;
498 SpdyFrameType header_control_type_;
499 bool header_buffer_valid_;
500 SpdyHeaderBlock headers_;
503 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
504 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
505 const SpdyFramer& framer) {
506 SpdyFrameReader reader(frame->data(), frame->size());
507 reader.Seek(2); // Seek past the frame length.
508 SpdyFrameType frame_type;
509 if (framer.protocol_version() > SPDY3) {
510 uint8 serialized_type;
511 reader.ReadUInt8(&serialized_type);
512 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
513 serialized_type);
514 DCHECK_EQ(HEADERS, frame_type);
515 uint8 flags;
516 reader.ReadUInt8(&flags);
517 if (flags & HEADERS_FLAG_PRIORITY) {
518 frame_type = SYN_STREAM;
520 } else {
521 uint16 serialized_type;
522 reader.ReadUInt16(&serialized_type);
523 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
524 serialized_type);
525 DCHECK(frame_type == HEADERS ||
526 frame_type == SYN_STREAM) << frame_type;
529 if (frame_type == SYN_STREAM) {
530 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
531 frame->size() - framer.GetSynStreamMinimumSize());
532 } else {
533 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
534 frame->size() - framer.GetHeadersMinimumSize());
538 } // namespace test
540 } // namespace net
542 using net::test::SetFrameLength;
543 using net::test::SetFrameFlags;
544 using net::test::CompareCharArraysWithHexError;
545 using net::test::SpdyFramerTestUtil;
546 using net::test::TestSpdyVisitor;
547 using net::test::GetSerializedHeaders;
549 namespace net {
551 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
552 protected:
553 virtual void SetUp() {
554 spdy_version_ = GetParam();
555 spdy_version_ch_ = static_cast<unsigned char>(
556 SpdyConstants::SerializeMajorVersion(spdy_version_));
559 void CompareFrame(const string& description,
560 const SpdyFrame& actual_frame,
561 const unsigned char* expected,
562 const int expected_len) {
563 const unsigned char* actual =
564 reinterpret_cast<const unsigned char*>(actual_frame.data());
565 CompareCharArraysWithHexError(
566 description, actual, actual_frame.size(), expected, expected_len);
569 void CompareFrames(const string& description,
570 const SpdyFrame& expected_frame,
571 const SpdyFrame& actual_frame) {
572 CompareCharArraysWithHexError(
573 description,
574 reinterpret_cast<const unsigned char*>(expected_frame.data()),
575 expected_frame.size(),
576 reinterpret_cast<const unsigned char*>(actual_frame.data()),
577 actual_frame.size());
580 // Returns true if the two header blocks have equivalent content.
581 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
582 const SpdyHeaderBlock* actual) {
583 if (expected->size() != actual->size()) {
584 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
585 << actual->size() << ".";
586 return false;
588 for (SpdyHeaderBlock::const_iterator it = expected->begin();
589 it != expected->end();
590 ++it) {
591 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
592 if (it2 == actual->end()) {
593 LOG(ERROR) << "Expected header name '" << it->first << "'.";
594 return false;
596 if (it->second.compare(it2->second) != 0) {
597 LOG(ERROR) << "Expected header named '" << it->first
598 << "' to have a value of '" << it->second
599 << "'. The actual value received was '" << it2->second
600 << "'.";
601 return false;
604 return true;
607 bool IsSpdy2() { return spdy_version_ == SPDY2; }
608 bool IsSpdy3() { return spdy_version_ == SPDY3; }
609 bool IsSpdy4() { return spdy_version_ == SPDY4; }
611 // Version of SPDY protocol to be used.
612 SpdyMajorVersion spdy_version_;
613 unsigned char spdy_version_ch_;
616 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
617 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
618 SpdyFramerTest,
619 ::testing::Values(SPDY2, SPDY3, SPDY4));
621 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
622 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
623 SpdyFramer framer(spdy_version_);
624 framer.set_enable_compression(false);
626 // Encode the header block into a SynStream frame.
627 SpdySynStreamIR syn_stream(1);
628 syn_stream.set_priority(1);
629 syn_stream.SetHeader("alpha", "beta");
630 syn_stream.SetHeader("gamma", "charlie");
631 syn_stream.SetHeader("cookie", "key1=value1; key2=value2");
632 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
633 EXPECT_TRUE(frame.get() != NULL);
635 TestSpdyVisitor visitor(spdy_version_);
636 visitor.use_compression_ = false;
637 visitor.SimulateInFramer(
638 reinterpret_cast<unsigned char*>(frame->data()),
639 frame->size());
641 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
642 EXPECT_TRUE(CompareHeaderBlocks(&syn_stream.name_value_block(),
643 &visitor.headers_));
646 // Test that if there's not a full frame, we fail to parse it.
647 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
648 SpdyFramer framer(spdy_version_);
649 framer.set_enable_compression(false);
651 // Encode the header block into a SynStream frame.
652 SpdySynStreamIR syn_stream(1);
653 syn_stream.set_priority(1);
654 syn_stream.SetHeader("alpha", "beta");
655 syn_stream.SetHeader("gamma", "charlie");
656 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
657 EXPECT_TRUE(frame.get() != NULL);
659 TestSpdyVisitor visitor(spdy_version_);
660 visitor.use_compression_ = false;
661 visitor.SimulateInFramer(
662 reinterpret_cast<unsigned char*>(frame->data()),
663 frame->size() - 2);
665 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
666 EXPECT_EQ(0u, visitor.headers_.size());
669 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
670 // (but don't crash).
671 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
672 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
673 SpdyFramer framer(spdy_version_);
674 framer.set_visitor(&visitor);
676 SpdySynReplyIR syn_reply(0);
677 syn_reply.SetHeader("alpha", "beta");
678 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
679 ASSERT_TRUE(frame.get() != NULL);
681 // We shouldn't have to read the whole frame before we signal an error.
682 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
683 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
684 EXPECT_TRUE(framer.HasError());
685 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
686 << SpdyFramer::ErrorCodeToString(framer.error_code());
689 // Test that if we receive a HEADERS with stream ID zero, we signal an error
690 // (but don't crash).
691 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
692 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
693 SpdyFramer framer(spdy_version_);
694 framer.set_visitor(&visitor);
696 SpdyHeadersIR headers_ir(0);
697 headers_ir.SetHeader("alpha", "beta");
698 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
699 ASSERT_TRUE(frame.get() != NULL);
701 // We shouldn't have to read the whole frame before we signal an error.
702 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
703 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
704 EXPECT_TRUE(framer.HasError());
705 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
706 << SpdyFramer::ErrorCodeToString(framer.error_code());
709 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
710 // error (but don't crash).
711 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
712 if (spdy_version_ <= SPDY3) {
713 return;
716 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
717 SpdyFramer framer(spdy_version_);
718 framer.set_visitor(&visitor);
720 SpdyPushPromiseIR push_promise(0, 4);
721 push_promise.SetHeader("alpha", "beta");
722 scoped_ptr<SpdySerializedFrame> frame(
723 framer.SerializePushPromise(push_promise));
724 ASSERT_TRUE(frame.get() != NULL);
726 // We shouldn't have to read the whole frame before we signal an error.
727 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
728 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
729 EXPECT_TRUE(framer.HasError());
730 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
731 << SpdyFramer::ErrorCodeToString(framer.error_code());
734 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
735 // signal an error (but don't crash).
736 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
737 if (spdy_version_ <= SPDY3) {
738 return;
741 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
742 SpdyFramer framer(spdy_version_);
743 framer.set_visitor(&visitor);
745 SpdyPushPromiseIR push_promise(3, 0);
746 push_promise.SetHeader("alpha", "beta");
747 scoped_ptr<SpdySerializedFrame> frame(
748 framer.SerializePushPromise(push_promise));
749 ASSERT_TRUE(frame.get() != NULL);
751 // We shouldn't have to read the whole frame before we signal an error.
752 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
753 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
754 EXPECT_TRUE(framer.HasError());
755 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
756 << SpdyFramer::ErrorCodeToString(framer.error_code());
759 TEST_P(SpdyFramerTest, DuplicateHeader) {
760 if (spdy_version_ > SPDY3) {
761 // TODO(jgraettinger): Punting on this because we haven't determined
762 // whether duplicate HPACK headers other than Cookie are an error.
763 // If they are, this will need to be updated to use HpackOutputStream.
764 return;
766 SpdyFramer framer(spdy_version_);
767 // Frame builder with plentiful buffer size.
768 SpdyFrameBuilder frame(1024, spdy_version_);
769 if (spdy_version_ <= SPDY3) {
770 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
771 frame.WriteUInt32(3); // stream_id
772 frame.WriteUInt32(0); // associated stream id
773 frame.WriteUInt16(0); // Priority.
774 } else {
775 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
776 frame.WriteUInt32(framer.GetHighestPriority());
779 if (IsSpdy2()) {
780 frame.WriteUInt16(2); // Number of headers.
781 frame.WriteString("name");
782 frame.WriteString("value1");
783 frame.WriteString("name");
784 frame.WriteString("value2");
785 } else {
786 frame.WriteUInt32(2); // Number of headers.
787 frame.WriteStringPiece32("name");
788 frame.WriteStringPiece32("value1");
789 frame.WriteStringPiece32("name");
790 frame.WriteStringPiece32("value2");
792 // write the length
793 frame.RewriteLength(framer);
795 SpdyHeaderBlock new_headers;
796 framer.set_enable_compression(false);
797 scoped_ptr<SpdyFrame> control_frame(frame.take());
798 base::StringPiece serialized_headers =
799 GetSerializedHeaders(control_frame.get(), framer);
800 // This should fail because duplicate headers are verboten by the spec.
801 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
802 serialized_headers.size(),
803 &new_headers));
806 TEST_P(SpdyFramerTest, MultiValueHeader) {
807 SpdyFramer framer(spdy_version_);
808 // Frame builder with plentiful buffer size.
809 SpdyFrameBuilder frame(1024, spdy_version_);
810 if (spdy_version_ <= SPDY3) {
811 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
812 frame.WriteUInt32(3); // stream_id
813 frame.WriteUInt32(0); // associated stream id
814 frame.WriteUInt16(0); // Priority.
815 } else {
816 frame.BeginNewFrame(framer,
817 HEADERS,
818 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
820 frame.WriteUInt32(framer.GetHighestPriority());
823 string value("value1\0value2", 13);
824 if (IsSpdy2()) {
825 frame.WriteUInt16(1); // Number of headers.
826 frame.WriteString("name");
827 frame.WriteString(value);
828 } else if (spdy_version_ > SPDY3) {
829 // TODO(jgraettinger): If this pattern appears again, move to test class.
830 std::map<string, string> header_set;
831 header_set["name"] = value;
832 string buffer;
833 HpackEncoder encoder(ObtainHpackHuffmanTable());
834 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
835 frame.WriteBytes(&buffer[0], buffer.size());
836 } else {
837 frame.WriteUInt32(1); // Number of headers.
838 frame.WriteStringPiece32("name");
839 frame.WriteStringPiece32(value);
841 // write the length
842 frame.RewriteLength(framer);
844 framer.set_enable_compression(false);
845 scoped_ptr<SpdyFrame> control_frame(frame.take());
847 TestSpdyVisitor visitor(spdy_version_);
848 visitor.use_compression_ = false;
849 visitor.SimulateInFramer(
850 reinterpret_cast<unsigned char*>(control_frame->data()),
851 control_frame->size());
853 EXPECT_THAT(visitor.headers_, ElementsAre(
854 Pair("name", value)));
857 TEST_P(SpdyFramerTest, BasicCompression) {
858 if (spdy_version_ > SPDY3) {
859 // Deflate compression doesn't apply to HPACK.
860 return;
862 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
863 SpdyFramer framer(spdy_version_);
864 framer.set_debug_visitor(visitor.get());
865 SpdySynStreamIR syn_stream(1);
866 syn_stream.set_priority(1);
867 syn_stream.SetHeader("server", "SpdyServer 1.0");
868 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
869 syn_stream.SetHeader("status", "200");
870 syn_stream.SetHeader("version", "HTTP/1.1");
871 syn_stream.SetHeader("content-type", "text/html");
872 syn_stream.SetHeader("content-length", "12");
873 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
874 size_t uncompressed_size1 = visitor->last_payload_len_;
875 size_t compressed_size1 =
876 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
877 if (IsSpdy2()) {
878 EXPECT_EQ(139u, uncompressed_size1);
879 #if defined(USE_SYSTEM_ZLIB)
880 EXPECT_EQ(155u, compressed_size1);
881 #else // !defined(USE_SYSTEM_ZLIB)
882 EXPECT_EQ(135u, compressed_size1);
883 #endif // !defined(USE_SYSTEM_ZLIB)
884 } else {
885 EXPECT_EQ(165u, uncompressed_size1);
886 #if defined(USE_SYSTEM_ZLIB)
887 EXPECT_EQ(181u, compressed_size1);
888 #else // !defined(USE_SYSTEM_ZLIB)
889 EXPECT_EQ(117u, compressed_size1);
890 #endif // !defined(USE_SYSTEM_ZLIB)
892 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
893 size_t uncompressed_size2 = visitor->last_payload_len_;
894 size_t compressed_size2 =
895 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
897 // Expect the second frame to be more compact than the first.
898 EXPECT_LE(frame2->size(), frame1->size());
900 // Decompress the first frame
901 scoped_ptr<SpdyFrame> frame3(SpdyFramerTestUtil::DecompressFrame(
902 &framer, *frame1.get()));
904 // Decompress the second frame
905 visitor.reset(new TestSpdyVisitor(spdy_version_));
906 framer.set_debug_visitor(visitor.get());
907 scoped_ptr<SpdyFrame> frame4(SpdyFramerTestUtil::DecompressFrame(
908 &framer, *frame2.get()));
909 size_t uncompressed_size4 =
910 frame4->size() - framer.GetSynStreamMinimumSize();
911 size_t compressed_size4 =
912 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
913 if (IsSpdy2()) {
914 EXPECT_EQ(139u, uncompressed_size4);
915 #if defined(USE_SYSTEM_ZLIB)
916 EXPECT_EQ(149u, compressed_size4);
917 #else // !defined(USE_SYSTEM_ZLIB)
918 EXPECT_EQ(101u, compressed_size4);
919 #endif // !defined(USE_SYSTEM_ZLIB)
920 } else {
921 EXPECT_EQ(165u, uncompressed_size4);
922 #if defined(USE_SYSTEM_ZLIB)
923 EXPECT_EQ(175u, compressed_size4);
924 #else // !defined(USE_SYSTEM_ZLIB)
925 EXPECT_EQ(102u, compressed_size4);
926 #endif // !defined(USE_SYSTEM_ZLIB)
929 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
930 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
931 EXPECT_EQ(compressed_size2, compressed_size4);
933 // Expect frames 3 & 4 to be the same.
934 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
936 // Expect frames 3 to be the same as a uncompressed frame created
937 // from scratch.
938 framer.set_enable_compression(false);
939 scoped_ptr<SpdyFrame> uncompressed_frame(
940 framer.SerializeSynStream(syn_stream));
941 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
944 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
945 // See crbug.com/172383
946 SpdySynStreamIR syn_stream(1);
947 syn_stream.SetHeader("server", "SpdyServer 1.0");
948 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
949 syn_stream.SetHeader("status", "200");
950 syn_stream.SetHeader("version", "HTTP/1.1");
951 syn_stream.SetHeader("content-type", "text/html");
952 syn_stream.SetHeader("content-length", "12");
953 syn_stream.SetHeader("x-empty-header", "");
955 SpdyFramer framer(spdy_version_);
956 framer.set_enable_compression(true);
957 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
960 TEST_P(SpdyFramerTest, Basic) {
961 const unsigned char kV2Input[] = {
962 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
963 0x00, 0x00, 0x00, 0x14,
964 0x00, 0x00, 0x00, 0x01,
965 0x00, 0x00, 0x00, 0x00,
966 0x00, 0x00, 0x00, 0x01,
967 0x00, 0x02, 'h', 'h',
968 0x00, 0x02, 'v', 'v',
970 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
971 0x00, 0x00, 0x00, 0x18,
972 0x00, 0x00, 0x00, 0x01,
973 0x00, 0x00, 0x00, 0x02,
974 0x00, 0x02, 'h', '2',
975 0x00, 0x02, 'v', '2',
976 0x00, 0x02, 'h', '3',
977 0x00, 0x02, 'v', '3',
979 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
980 0x00, 0x00, 0x00, 0x0c,
981 0xde, 0xad, 0xbe, 0xef,
982 0xde, 0xad, 0xbe, 0xef,
983 0xde, 0xad, 0xbe, 0xef,
985 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
986 0x00, 0x00, 0x00, 0x0c,
987 0x00, 0x00, 0x00, 0x03,
988 0x00, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
992 0x00, 0x00, 0x00, 0x08,
993 0xde, 0xad, 0xbe, 0xef,
994 0xde, 0xad, 0xbe, 0xef,
996 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
997 0x00, 0x00, 0x00, 0x04,
998 0xde, 0xad, 0xbe, 0xef,
1000 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1001 0x00, 0x00, 0x00, 0x08,
1002 0x00, 0x00, 0x00, 0x01,
1003 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1005 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1006 0x00, 0x00, 0x00, 0x00,
1008 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1009 0x00, 0x00, 0x00, 0x08,
1010 0x00, 0x00, 0x00, 0x03,
1011 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1014 const unsigned char kV3Input[] = {
1015 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1016 0x00, 0x00, 0x00, 0x1a,
1017 0x00, 0x00, 0x00, 0x01,
1018 0x00, 0x00, 0x00, 0x00,
1019 0x00, 0x00, 0x00, 0x00,
1020 0x00, 0x01, 0x00, 0x00,
1021 0x00, 0x02, 'h', 'h',
1022 0x00, 0x00, 0x00, 0x02,
1023 'v', 'v',
1025 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1026 0x00, 0x00, 0x00, 0x20,
1027 0x00, 0x00, 0x00, 0x01,
1028 0x00, 0x00, 0x00, 0x02,
1029 0x00, 0x00, 0x00, 0x02,
1030 'h', '2',
1031 0x00, 0x00, 0x00, 0x02,
1032 'v', '2', 0x00, 0x00,
1033 0x00, 0x02, 'h', '3',
1034 0x00, 0x00, 0x00, 0x02,
1035 'v', '3',
1037 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1038 0x00, 0x00, 0x00, 0x0c,
1039 0xde, 0xad, 0xbe, 0xef,
1040 0xde, 0xad, 0xbe, 0xef,
1041 0xde, 0xad, 0xbe, 0xef,
1043 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1044 0x00, 0x00, 0x00, 0x0e,
1045 0x00, 0x00, 0x00, 0x03,
1046 0x00, 0x00, 0x00, 0x00,
1047 0x00, 0x00, 0x00, 0x00,
1048 0x00, 0x00,
1050 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1051 0x00, 0x00, 0x00, 0x08,
1052 0xde, 0xad, 0xbe, 0xef,
1053 0xde, 0xad, 0xbe, 0xef,
1055 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1056 0x00, 0x00, 0x00, 0x04,
1057 0xde, 0xad, 0xbe, 0xef,
1059 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1060 0x00, 0x00, 0x00, 0x08,
1061 0x00, 0x00, 0x00, 0x01,
1062 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1064 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1065 0x00, 0x00, 0x00, 0x00,
1067 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1068 0x00, 0x00, 0x00, 0x08,
1069 0x00, 0x00, 0x00, 0x03,
1070 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1073 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1074 // HEADERS frames with PRIORITY and END_HEADERS set.
1075 const unsigned char kV4Input[] = {
1076 0x00, 0x05, 0x01, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1077 0x00, 0x00, 0x00, 0x01, // Stream 1
1078 0x00, 0x00, 0x00, 0x00, // Priority 0
1079 0x82, // :method: GET
1081 0x00, 0x01, 0x01, 0x04, // HEADERS: END_HEADERS
1082 0x00, 0x00, 0x00, 0x01, // Stream 1
1083 0x8c, // :status: 200
1085 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1
1086 0x00, 0x00, 0x00, 0x01,
1087 0xde, 0xad, 0xbe, 0xef,
1088 0xde, 0xad, 0xbe, 0xef,
1089 0xde, 0xad, 0xbe, 0xef,
1091 0x00, 0x05, 0x01, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1092 0x00, 0x00, 0x00, 0x03, // Stream 3
1093 0x00, 0x00, 0x00, 0x00, // Priority 0
1094 0x82, // :method: GET
1096 0x00, 0x08, 0x00, 0x00, // DATA on Stream #3
1097 0x00, 0x00, 0x00, 0x03,
1098 0xde, 0xad, 0xbe, 0xef,
1099 0xde, 0xad, 0xbe, 0xef,
1101 0x00, 0x04, 0x00, 0x00, // DATA on Stream #1
1102 0x00, 0x00, 0x00, 0x01,
1103 0xde, 0xad, 0xbe, 0xef,
1105 0x00, 0x04, 0x03, 0x00, // RST_STREAM on Stream #1
1106 0x00, 0x00, 0x00, 0x01,
1107 0x00, 0x00, 0x00, 0x08, // RST_STREAM_CANCEL
1109 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1110 0x00, 0x00, 0x00, 0x03,
1112 0x00, 0x0f, 0x03, 0x00, // RST_STREAM on Stream #3
1113 0x00, 0x00, 0x00, 0x03,
1114 0x00, 0x00, 0x00, 0x08, // RST_STREAM_CANCEL
1115 0x52, 0x45, 0x53, 0x45, // opaque data
1116 0x54, 0x53, 0x54, 0x52,
1117 0x45, 0x41, 0x4d,
1120 TestSpdyVisitor visitor(spdy_version_);
1121 if (IsSpdy2()) {
1122 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1123 } else if (IsSpdy3()) {
1124 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1125 } else {
1126 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1129 EXPECT_EQ(2, visitor.syn_frame_count_);
1130 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1131 EXPECT_EQ(1, visitor.headers_frame_count_);
1132 EXPECT_EQ(24, visitor.data_bytes_);
1134 EXPECT_EQ(0, visitor.error_count_);
1135 EXPECT_EQ(2, visitor.fin_frame_count_);
1137 if (IsSpdy4()) {
1138 base::StringPiece reset_stream = "RESETSTREAM";
1139 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1140 } else {
1141 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1144 EXPECT_EQ(0, visitor.fin_flag_count_);
1145 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1146 EXPECT_EQ(4, visitor.data_frame_count_);
1147 visitor.fin_opaque_data_.clear();
1150 // Test that the FIN flag on a data frame signifies EOF.
1151 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1152 const unsigned char kV2Input[] = {
1153 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1154 0x00, 0x00, 0x00, 0x14,
1155 0x00, 0x00, 0x00, 0x01,
1156 0x00, 0x00, 0x00, 0x00,
1157 0x00, 0x00, 0x00, 0x01,
1158 0x00, 0x02, 'h', 'h',
1159 0x00, 0x02, 'v', 'v',
1161 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1162 0x00, 0x00, 0x00, 0x10,
1163 0x00, 0x00, 0x00, 0x01,
1164 0x00, 0x00, 0x00, 0x01,
1165 0x00, 0x02, 'a', 'a',
1166 0x00, 0x02, 'b', 'b',
1168 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1169 0x00, 0x00, 0x00, 0x0c,
1170 0xde, 0xad, 0xbe, 0xef,
1171 0xde, 0xad, 0xbe, 0xef,
1172 0xde, 0xad, 0xbe, 0xef,
1174 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1175 0x01, 0x00, 0x00, 0x04,
1176 0xde, 0xad, 0xbe, 0xef,
1178 const unsigned char kV3Input[] = {
1179 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1180 0x00, 0x00, 0x00, 0x1a,
1181 0x00, 0x00, 0x00, 0x01,
1182 0x00, 0x00, 0x00, 0x00,
1183 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x01, 0x00, 0x00,
1185 0x00, 0x02, 'h', 'h',
1186 0x00, 0x00, 0x00, 0x02,
1187 'v', 'v',
1189 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1190 0x00, 0x00, 0x00, 0x14,
1191 0x00, 0x00, 0x00, 0x01,
1192 0x00, 0x00, 0x00, 0x01,
1193 0x00, 0x00, 0x00, 0x02,
1194 'a', 'a', 0x00, 0x00,
1195 0x00, 0x02, 'b', 'b',
1197 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1198 0x00, 0x00, 0x00, 0x0c,
1199 0xde, 0xad, 0xbe, 0xef,
1200 0xde, 0xad, 0xbe, 0xef,
1201 0xde, 0xad, 0xbe, 0xef,
1203 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1204 0x01, 0x00, 0x00, 0x04,
1205 0xde, 0xad, 0xbe, 0xef,
1208 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1209 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1210 const unsigned char kV4Input[] = {
1211 0x00, 0x05, 0x01, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1212 0x00, 0x00, 0x00, 0x01, // Stream 1
1213 0x00, 0x00, 0x00, 0x00, // Priority 0
1214 0x82, // :method: GET
1216 0x00, 0x01, 0x01, 0x04, // HEADERS: END_HEADERS
1217 0x00, 0x00, 0x00, 0x01, // Stream 1
1218 0x8c, // :status: 200
1220 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1
1221 0x00, 0x00, 0x00, 0x01,
1222 0xde, 0xad, 0xbe, 0xef,
1223 0xde, 0xad, 0xbe, 0xef,
1224 0xde, 0xad, 0xbe, 0xef,
1226 0x00, 0x04, 0x00, 0x01, // DATA on Stream #1, with FIN
1227 0x00, 0x00, 0x00, 0x01,
1228 0xde, 0xad, 0xbe, 0xef,
1231 TestSpdyVisitor visitor(spdy_version_);
1232 if (IsSpdy2()) {
1233 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1234 } else if (IsSpdy3()) {
1235 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1236 } else {
1237 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1240 EXPECT_EQ(0, visitor.error_count_);
1241 EXPECT_EQ(1, visitor.syn_frame_count_);
1242 if (IsSpdy4()) {
1243 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1244 EXPECT_EQ(1, visitor.headers_frame_count_);
1245 } else {
1246 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1247 EXPECT_EQ(0, visitor.headers_frame_count_);
1249 EXPECT_EQ(16, visitor.data_bytes_);
1250 EXPECT_EQ(0, visitor.fin_frame_count_);
1251 EXPECT_EQ(0, visitor.fin_flag_count_);
1252 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1253 EXPECT_EQ(2, visitor.data_frame_count_);
1256 // Test that the FIN flag on a SYN reply frame signifies EOF.
1257 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1258 const unsigned char kV2Input[] = {
1259 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1260 0x00, 0x00, 0x00, 0x14,
1261 0x00, 0x00, 0x00, 0x01,
1262 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x01,
1264 0x00, 0x02, 'h', 'h',
1265 0x00, 0x02, 'v', 'v',
1267 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1268 0x01, 0x00, 0x00, 0x10,
1269 0x00, 0x00, 0x00, 0x01,
1270 0x00, 0x00, 0x00, 0x01,
1271 0x00, 0x02, 'a', 'a',
1272 0x00, 0x02, 'b', 'b',
1274 const unsigned char kV3Input[] = {
1275 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1276 0x00, 0x00, 0x00, 0x1a,
1277 0x00, 0x00, 0x00, 0x01,
1278 0x00, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00,
1280 0x00, 0x01, 0x00, 0x00,
1281 0x00, 0x02, 'h', 'h',
1282 0x00, 0x00, 0x00, 0x02,
1283 'v', 'v',
1285 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1286 0x01, 0x00, 0x00, 0x14,
1287 0x00, 0x00, 0x00, 0x01,
1288 0x00, 0x00, 0x00, 0x01,
1289 0x00, 0x00, 0x00, 0x02,
1290 'a', 'a', 0x00, 0x00,
1291 0x00, 0x02, 'b', 'b',
1294 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1295 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1296 const unsigned char kV4Input[] = {
1297 0x00, 0x05, 0x01, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1298 0x00, 0x00, 0x00, 0x01, // Stream 1
1299 0x00, 0x00, 0x00, 0x00, // Priority 0
1300 0x82, // :method: GET
1302 0x00, 0x01, 0x01, 0x05, // HEADERS: FIN | END_HEADERS
1303 0x00, 0x00, 0x00, 0x01, // Stream 1
1304 0x8c, // :status: 200
1307 TestSpdyVisitor visitor(spdy_version_);
1308 if (IsSpdy2()) {
1309 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1310 } else if (IsSpdy3()) {
1311 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1312 } else {
1313 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1316 EXPECT_EQ(0, visitor.error_count_);
1317 EXPECT_EQ(1, visitor.syn_frame_count_);
1318 if (IsSpdy4()) {
1319 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1320 EXPECT_EQ(1, visitor.headers_frame_count_);
1321 } else {
1322 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1323 EXPECT_EQ(0, visitor.headers_frame_count_);
1325 EXPECT_EQ(0, visitor.data_bytes_);
1326 EXPECT_EQ(0, visitor.fin_frame_count_);
1327 EXPECT_EQ(1, visitor.fin_flag_count_);
1328 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1329 EXPECT_EQ(0, visitor.data_frame_count_);
1332 TEST_P(SpdyFramerTest, HeaderCompression) {
1333 if (spdy_version_ > SPDY3) {
1334 // Deflate compression doesn't apply to HPACK.
1335 return;
1337 SpdyFramer send_framer(spdy_version_);
1338 SpdyFramer recv_framer(spdy_version_);
1340 send_framer.set_enable_compression(true);
1341 recv_framer.set_enable_compression(true);
1343 const char kHeader1[] = "header1";
1344 const char kHeader2[] = "header2";
1345 const char kHeader3[] = "header3";
1346 const char kValue1[] = "value1";
1347 const char kValue2[] = "value2";
1348 const char kValue3[] = "value3";
1350 // SYN_STREAM #1
1351 SpdyHeaderBlock block;
1352 block[kHeader1] = kValue1;
1353 block[kHeader2] = kValue2;
1354 SpdySynStreamIR syn_ir_1(1);
1355 syn_ir_1.set_name_value_block(block);
1356 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1357 EXPECT_TRUE(syn_frame_1.get() != NULL);
1359 // SYN_STREAM #2
1360 block[kHeader3] = kValue3;
1361 SpdySynStreamIR syn_stream(3);
1362 syn_stream.set_name_value_block(block);
1363 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1364 EXPECT_TRUE(syn_frame_2.get() != NULL);
1366 // Now start decompressing
1367 scoped_ptr<SpdyFrame> decompressed;
1368 scoped_ptr<SpdyFrame> uncompressed;
1369 base::StringPiece serialized_headers;
1370 SpdyHeaderBlock decompressed_headers;
1372 // Decompress SYN_STREAM #1
1373 decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
1374 &recv_framer, *syn_frame_1.get()));
1375 EXPECT_TRUE(decompressed.get() != NULL);
1376 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1377 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1378 serialized_headers.size(),
1379 &decompressed_headers));
1380 EXPECT_EQ(2u, decompressed_headers.size());
1381 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1382 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1384 // Decompress SYN_STREAM #2
1385 decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
1386 &recv_framer, *syn_frame_2.get()));
1387 EXPECT_TRUE(decompressed.get() != NULL);
1388 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1389 decompressed_headers.clear();
1390 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1391 serialized_headers.size(),
1392 &decompressed_headers));
1393 EXPECT_EQ(3u, decompressed_headers.size());
1394 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1395 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1396 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1399 // Verify we don't leak when we leave streams unclosed
1400 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressors) {
1401 SpdyFramer send_framer(spdy_version_);
1403 send_framer.set_enable_compression(true);
1405 const char kHeader1[] = "header1";
1406 const char kHeader2[] = "header2";
1407 const char kValue1[] = "value1";
1408 const char kValue2[] = "value2";
1410 SpdySynStreamIR syn_stream(1);
1411 syn_stream.SetHeader(kHeader1, kValue1);
1412 syn_stream.SetHeader(kHeader2, kValue2);
1413 scoped_ptr<SpdyFrame> syn_frame(send_framer.SerializeSynStream(syn_stream));
1414 EXPECT_TRUE(syn_frame.get() != NULL);
1416 StringPiece bytes = "this is a test test test test test!";
1417 SpdyDataIR data_ir(1, bytes);
1418 data_ir.set_fin(true);
1419 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1420 EXPECT_TRUE(send_frame.get() != NULL);
1422 // Run the inputs through the framer.
1423 TestSpdyVisitor visitor(spdy_version_);
1424 visitor.use_compression_ = true;
1425 const unsigned char* data;
1426 data = reinterpret_cast<const unsigned char*>(syn_frame->data());
1427 visitor.SimulateInFramer(data, syn_frame->size());
1428 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1429 visitor.SimulateInFramer(data, send_frame->size());
1431 EXPECT_EQ(0, visitor.error_count_);
1432 EXPECT_EQ(1, visitor.syn_frame_count_);
1433 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1434 EXPECT_EQ(0, visitor.headers_frame_count_);
1435 EXPECT_EQ(bytes.size(), static_cast<unsigned>(visitor.data_bytes_));
1436 EXPECT_EQ(0, visitor.fin_frame_count_);
1437 EXPECT_EQ(0, visitor.fin_flag_count_);
1438 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1439 EXPECT_EQ(1, visitor.data_frame_count_);
1442 // Verify we can decompress the stream even if handed over to the
1443 // framer 1 byte at a time.
1444 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1445 SpdyFramer send_framer(spdy_version_);
1447 send_framer.set_enable_compression(true);
1449 const char kHeader1[] = "header1";
1450 const char kHeader2[] = "header2";
1451 const char kValue1[] = "value1";
1452 const char kValue2[] = "value2";
1454 SpdySynStreamIR syn_stream(1);
1455 syn_stream.SetHeader(kHeader1, kValue1);
1456 syn_stream.SetHeader(kHeader2, kValue2);
1457 scoped_ptr<SpdyFrame> syn_frame(send_framer.SerializeSynStream(syn_stream));
1458 EXPECT_TRUE(syn_frame.get() != NULL);
1460 const char bytes[] = "this is a test test test test test!";
1461 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1462 data_ir.set_fin(true);
1463 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1464 EXPECT_TRUE(send_frame.get() != NULL);
1466 // Run the inputs through the framer.
1467 TestSpdyVisitor visitor(spdy_version_);
1468 visitor.use_compression_ = true;
1469 const unsigned char* data;
1470 data = reinterpret_cast<const unsigned char*>(syn_frame->data());
1471 for (size_t idx = 0; idx < syn_frame->size(); ++idx) {
1472 visitor.SimulateInFramer(data + idx, 1);
1473 ASSERT_EQ(0, visitor.error_count_);
1475 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1476 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1477 visitor.SimulateInFramer(data + idx, 1);
1478 ASSERT_EQ(0, visitor.error_count_);
1481 EXPECT_EQ(0, visitor.error_count_);
1482 EXPECT_EQ(1, visitor.syn_frame_count_);
1483 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1484 EXPECT_EQ(0, visitor.headers_frame_count_);
1485 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1486 EXPECT_EQ(0, visitor.fin_frame_count_);
1487 EXPECT_EQ(0, visitor.fin_flag_count_);
1488 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1489 EXPECT_EQ(1, visitor.data_frame_count_);
1492 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1493 SpdyFramer framer(spdy_version_);
1494 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1495 SpdyWindowUpdateIR(1, 0x12345678)));
1497 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1498 const unsigned char kV3FrameData[] = { // Also applies for V2.
1499 0x80, spdy_version_ch_, 0x00, 0x09,
1500 0x00, 0x00, 0x00, 0x08,
1501 0x00, 0x00, 0x00, 0x01,
1502 0x12, 0x34, 0x56, 0x78
1504 const unsigned char kV4FrameData[] = {
1505 0x00, 0x04, 0x08, 0x00,
1506 0x00, 0x00, 0x00, 0x01,
1507 0x12, 0x34, 0x56, 0x78
1510 if (IsSpdy4()) {
1511 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1512 } else {
1513 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1517 TEST_P(SpdyFramerTest, CreateDataFrame) {
1518 SpdyFramer framer(spdy_version_);
1521 const char kDescription[] = "'hello' data frame, no FIN";
1522 const unsigned char kV3FrameData[] = { // Also applies for V2.
1523 0x00, 0x00, 0x00, 0x01,
1524 0x00, 0x00, 0x00, 0x05,
1525 'h', 'e', 'l', 'l',
1528 const unsigned char kV4FrameData[] = {
1529 0x00, 0x05, 0x00, 0x00,
1530 0x00, 0x00, 0x00, 0x01,
1531 'h', 'e', 'l', 'l',
1534 const char bytes[] = "hello";
1536 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1537 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1538 if (IsSpdy4()) {
1539 CompareFrame(
1540 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1541 } else {
1542 CompareFrame(
1543 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1546 SpdyDataIR data_header_ir(1);
1547 data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
1548 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1549 data_header_ir));
1550 CompareCharArraysWithHexError(
1551 kDescription,
1552 reinterpret_cast<const unsigned char*>(frame->data()),
1553 framer.GetDataFrameMinimumSize(),
1554 IsSpdy4() ? kV4FrameData : kV3FrameData,
1555 framer.GetDataFrameMinimumSize());
1559 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1560 const unsigned char kV3FrameData[] = { // Also applies for V2.
1561 0x00, 0x00, 0x00, 0x01,
1562 0x00, 0x00, 0x00, 0x05,
1563 'h', 'e', 'l', 'l',
1567 const unsigned char kV4FrameData[] = {
1568 0x01, 0x0b, 0x00, 0x30, // Length = 267. PAD_HIGH and PAD_LOW set.
1569 0x00, 0x00, 0x00, 0x01,
1570 0x01, 0x04, // Pad Low and Pad High fields.
1571 'h', 'e', 'l', 'l', // Data
1572 'o',
1573 // Padding of 260 zeros (so both PAD_HIGH and PAD_LOW fields are used).
1574 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1575 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1576 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1577 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1578 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1579 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1580 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1581 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1582 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1583 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1584 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1585 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1586 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1587 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1588 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1589 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1590 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1591 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1592 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1593 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1595 const char bytes[] = "hello";
1597 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1598 // 260 zeros and the pad low/high fields make the overall padding to be 262
1599 // bytes.
1600 data_ir.set_padding_len(262);
1601 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1602 if (IsSpdy4()) {
1603 CompareFrame(
1604 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1605 } else {
1606 CompareFrame(
1607 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1610 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1611 CompareCharArraysWithHexError(
1612 kDescription,
1613 reinterpret_cast<const unsigned char*>(frame->data()),
1614 framer.GetDataFrameMinimumSize(),
1615 IsSpdy4() ? kV4FrameData : kV3FrameData,
1616 framer.GetDataFrameMinimumSize());
1620 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1621 const unsigned char kV3FrameData[] = { // Also applies for V2.
1622 0x00, 0x00, 0x00, 0x01,
1623 0x00, 0x00, 0x00, 0x05,
1624 'h', 'e', 'l', 'l',
1628 const unsigned char kV4FrameData[] = {
1629 0x00, 0x0d, 0x00, 0x10, // Length = 13. PAD_LOW set.
1630 0x00, 0x00, 0x00, 0x01,
1631 0x07, // Pad Low field.
1632 'h', 'e', 'l', 'l', // Data
1633 'o',
1634 '0', '0', '0', '0', // Padding
1635 '0', '0', '0'
1637 const char bytes[] = "hello";
1639 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1640 // 7 zeros and the pad low field make the overall padding to be 8 bytes.
1641 data_ir.set_padding_len(8);
1642 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1643 if (IsSpdy4()) {
1644 CompareFrame(
1645 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1646 } else {
1647 CompareFrame(
1648 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1653 const char kDescription[] =
1654 "'hello' data frame with 1 byte padding, no FIN";
1655 const unsigned char kV3FrameData[] = { // Also applies for V2.
1656 0x00, 0x00, 0x00, 0x01,
1657 0x00, 0x00, 0x00, 0x05,
1658 'h', 'e', 'l', 'l',
1662 const unsigned char kV4FrameData[] = {
1663 0x00, 0x06, 0x00, 0x10, // Length = 6. PAD_LOW set.
1664 0x00, 0x00, 0x00, 0x01,
1665 0x00, // Pad Low field.
1666 'h', 'e', 'l', 'l', // Data
1667 'o',
1669 const char bytes[] = "hello";
1671 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1672 // The pad low field itself is used for the 1-byte padding and no padding
1673 // payload is needed.
1674 data_ir.set_padding_len(1);
1675 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1676 if (IsSpdy4()) {
1677 CompareFrame(
1678 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1679 } else {
1680 CompareFrame(
1681 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1684 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1685 CompareCharArraysWithHexError(
1686 kDescription,
1687 reinterpret_cast<const unsigned char*>(frame->data()),
1688 framer.GetDataFrameMinimumSize(),
1689 IsSpdy4() ? kV4FrameData : kV3FrameData,
1690 framer.GetDataFrameMinimumSize());
1694 const char kDescription[] = "Data frame with negative data byte, no FIN";
1695 const unsigned char kV3FrameData[] = { // Also applies for V2.
1696 0x00, 0x00, 0x00, 0x01,
1697 0x00, 0x00, 0x00, 0x01,
1698 0xff
1700 const unsigned char kV4FrameData[] = {
1701 0x00, 0x01, 0x00, 0x00,
1702 0x00, 0x00, 0x00, 0x01,
1703 0xff
1705 SpdyDataIR data_ir(1, StringPiece("\xff", 1));
1706 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1707 if (IsSpdy4()) {
1708 CompareFrame(
1709 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1710 } else {
1711 CompareFrame(
1712 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1717 const char kDescription[] = "'hello' data frame, with FIN";
1718 const unsigned char kV3FrameData[] = { // Also applies for V2.
1719 0x00, 0x00, 0x00, 0x01,
1720 0x01, 0x00, 0x00, 0x05,
1721 'h', 'e', 'l', 'l',
1724 const unsigned char kV4FrameData[] = {
1725 0x00, 0x05, 0x00, 0x01,
1726 0x00, 0x00, 0x00, 0x01,
1727 'h', 'e', 'l', 'l',
1730 SpdyDataIR data_ir(1, StringPiece("hello", 5));
1731 data_ir.set_fin(true);
1732 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1733 if (IsSpdy4()) {
1734 CompareFrame(
1735 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1736 } else {
1737 CompareFrame(
1738 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1743 const char kDescription[] = "Empty data frame";
1744 const unsigned char kV3FrameData[] = { // Also applies for V2.
1745 0x00, 0x00, 0x00, 0x01,
1746 0x00, 0x00, 0x00, 0x00,
1748 const unsigned char kV4FrameData[] = {
1749 0x00, 0x00, 0x00, 0x00,
1750 0x00, 0x00, 0x00, 0x01,
1752 SpdyDataIR data_ir(1, StringPiece());
1753 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1754 if (IsSpdy4()) {
1755 CompareFrame(
1756 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1757 } else {
1758 CompareFrame(
1759 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1762 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1763 CompareCharArraysWithHexError(
1764 kDescription,
1765 reinterpret_cast<const unsigned char*>(frame->data()),
1766 framer.GetDataFrameMinimumSize(),
1767 IsSpdy4() ? kV4FrameData : kV3FrameData,
1768 framer.GetDataFrameMinimumSize());
1772 const char kDescription[] = "Data frame with max stream ID";
1773 const unsigned char kV3FrameData[] = { // Also applies for V2.
1774 0x7f, 0xff, 0xff, 0xff,
1775 0x01, 0x00, 0x00, 0x05,
1776 'h', 'e', 'l', 'l',
1779 const unsigned char kV4FrameData[] = {
1780 0x00, 0x05, 0x00, 0x01,
1781 0x7f, 0xff, 0xff, 0xff,
1782 'h', 'e', 'l', 'l',
1785 SpdyDataIR data_ir(0x7fffffff, "hello");
1786 data_ir.set_fin(true);
1787 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1788 if (IsSpdy4()) {
1789 CompareFrame(
1790 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1791 } else {
1792 CompareFrame(
1793 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1797 if (!IsSpdy4()) {
1798 // This test does not apply to SPDY 4 because the max frame size is smaller
1799 // than 4MB.
1800 const char kDescription[] = "Large data frame";
1801 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1802 const string kData(kDataSize, 'A');
1803 const unsigned char kFrameHeader[] = {
1804 0x00, 0x00, 0x00, 0x01,
1805 0x01, 0x40, 0x00, 0x00,
1808 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1809 scoped_ptr<unsigned char[]> expected_frame_data(
1810 new unsigned char[kFrameSize]);
1811 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1812 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1814 SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
1815 data_ir.set_fin(true);
1816 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1817 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1821 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1822 SpdyFramer framer(spdy_version_);
1823 framer.set_enable_compression(false);
1826 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1828 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1829 const unsigned char kV2FrameData[] = {
1830 0x80, spdy_version_ch_, 0x00, 0x01,
1831 0x00, 0x00, 0x00, 0x20,
1832 0x00, 0x00, 0x00, 0x01,
1833 0x00, 0x00, 0x00, 0x00,
1834 kPri, 0x00, 0x00, 0x02,
1835 0x00, 0x03, 'b', 'a',
1836 'r', 0x00, 0x03, 'f',
1837 'o', 'o', 0x00, 0x03,
1838 'f', 'o', 'o', 0x00,
1839 0x03, 'b', 'a', 'r'
1841 const unsigned char kV3FrameData[] = {
1842 0x80, spdy_version_ch_, 0x00, 0x01,
1843 0x00, 0x00, 0x00, 0x2a,
1844 0x00, 0x00, 0x00, 0x01,
1845 0x00, 0x00, 0x00, 0x00,
1846 kPri, 0x00, 0x00, 0x00,
1847 0x00, 0x02, 0x00, 0x00,
1848 0x00, 0x03, 'b', 'a',
1849 'r', 0x00, 0x00, 0x00,
1850 0x03, 'f', 'o', 'o',
1851 0x00, 0x00, 0x00, 0x03,
1852 'f', 'o', 'o', 0x00,
1853 0x00, 0x00, 0x03, 'b',
1854 'a', 'r'
1856 const unsigned char kV4FrameData[] = {
1857 0x00, 0x16, 0x01, 0x0c, // HEADERS: PRIORITY | END_HEADERS
1858 0x00, 0x00, 0x00, 0x01, // Stream 1
1859 0x00, 0x00, 0x00, 0x07, // Priority 7
1860 0x40, 0x03, 0x62, 0x61, // @.ba
1861 0x72, 0x03, 0x66, 0x6f, // r.fo
1862 0x6f, 0x40, 0x03, 0x66, // o@.f
1863 0x6f, 0x6f, 0x03, 0x62, // oo.b
1864 0x61, 0x72, // ar
1866 SpdySynStreamIR syn_stream(1);
1867 syn_stream.set_priority(framer.GetLowestPriority());
1868 syn_stream.SetHeader("bar", "foo");
1869 syn_stream.SetHeader("foo", "bar");
1870 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1871 if (IsSpdy2()) {
1872 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1873 } else if (IsSpdy3()) {
1874 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1875 } else {
1876 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1881 const char kDescription[] =
1882 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1883 "max stream ID";
1885 const unsigned char kV2FrameData[] = {
1886 0x80, spdy_version_ch_, 0x00, 0x01,
1887 0x01, 0x00, 0x00, 0x1D,
1888 0x7f, 0xff, 0xff, 0xff,
1889 0x7f, 0xff, 0xff, 0xff,
1890 0x00, 0x00, 0x00, 0x02,
1891 0x00, 0x00, 0x00, 0x03,
1892 'f', 'o', 'o', 0x00,
1893 0x03, 'f', 'o', 'o',
1894 0x00, 0x03, 'b', 'a',
1897 const unsigned char kV3FrameData[] = {
1898 0x80, spdy_version_ch_, 0x00, 0x01,
1899 0x01, 0x00, 0x00, 0x27,
1900 0x7f, 0xff, 0xff, 0xff,
1901 0x7f, 0xff, 0xff, 0xff,
1902 0x00, 0x00, 0x00, 0x00,
1903 0x00, 0x02, 0x00, 0x00,
1904 0x00, 0x00, 0x00, 0x00,
1905 0x00, 0x03, 'f', 'o',
1906 'o', 0x00, 0x00, 0x00,
1907 0x03, 'f', 'o', 'o',
1908 0x00, 0x00, 0x00, 0x03,
1909 'b', 'a', 'r'
1911 const unsigned char kV4FrameData[] = {
1912 0x00, 0x13, 0x01, 0x0d, // HEADERS: PRIORITY | FIN | END_HEADERS
1913 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1914 0x00, 0x00, 0x00, 0x00, // Priority 0
1915 0x40, 0x00, 0x03, 0x66, // @..f
1916 0x6f, 0x6f, 0x40, 0x03, // oo@.
1917 0x66, 0x6f, 0x6f, 0x03, // foo.
1918 0x62, 0x61, 0x72, // bar
1920 SpdySynStreamIR syn_stream(0x7fffffff);
1921 syn_stream.set_associated_to_stream_id(0x7fffffff);
1922 syn_stream.set_priority(framer.GetHighestPriority());
1923 syn_stream.set_fin(true);
1924 syn_stream.SetHeader("", "foo");
1925 syn_stream.SetHeader("foo", "bar");
1926 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1927 if (IsSpdy2()) {
1928 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1929 } else if (IsSpdy3()) {
1930 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1931 } else {
1932 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1937 const char kDescription[] =
1938 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1939 "max stream ID";
1941 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
1942 const unsigned char kV2FrameData[] = {
1943 0x80, spdy_version_ch_, 0x00, 0x01,
1944 0x01, 0x00, 0x00, 0x1D,
1945 0x7f, 0xff, 0xff, 0xff,
1946 0x7f, 0xff, 0xff, 0xff,
1947 kPri, 0x00, 0x00, 0x02,
1948 0x00, 0x03, 'b', 'a',
1949 'r', 0x00, 0x03, 'f',
1950 'o', 'o', 0x00, 0x03,
1951 'f', 'o', 'o', 0x00,
1952 0x00
1954 const unsigned char kV3FrameData[] = {
1955 0x80, spdy_version_ch_, 0x00, 0x01,
1956 0x01, 0x00, 0x00, 0x27,
1957 0x7f, 0xff, 0xff, 0xff,
1958 0x7f, 0xff, 0xff, 0xff,
1959 kPri, 0x00, 0x00, 0x00,
1960 0x00, 0x02, 0x00, 0x00,
1961 0x00, 0x03, 'b', 'a',
1962 'r', 0x00, 0x00, 0x00,
1963 0x03, 'f', 'o', 'o',
1964 0x00, 0x00, 0x00, 0x03,
1965 'f', 'o', 'o', 0x00,
1966 0x00, 0x00, 0x00
1968 const unsigned char kV4FrameData[] = {
1969 0x00, 0x13, 0x01, 0x0d, // HEADERS: PRIORITY | FIN | END_HEADERS
1970 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
1971 0x00, 0x00, 0x00, 0x01, // Priority 1
1972 0x40, 0x03, 0x62, 0x61, // @.ba
1973 0x72, 0x03, 0x66, 0x6f, // r.fo
1974 0x6f, 0x40, 0x03, 0x66, // o@.f
1975 0x6f, 0x6f, 0x00, // oo.
1977 SpdySynStreamIR syn_stream(0x7fffffff);
1978 syn_stream.set_associated_to_stream_id(0x7fffffff);
1979 syn_stream.set_priority(1);
1980 syn_stream.set_fin(true);
1981 syn_stream.SetHeader("bar", "foo");
1982 syn_stream.SetHeader("foo", "");
1983 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1984 if (IsSpdy2()) {
1985 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1986 } else if (IsSpdy3()) {
1987 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1988 } else {
1989 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1994 // TODO(phajdan.jr): Clean up after we no longer need
1995 // to workaround http://crbug.com/139744.
1996 #if !defined(USE_SYSTEM_ZLIB)
1997 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
1998 SpdyFramer framer(spdy_version_);
1999 framer.set_enable_compression(true);
2002 const char kDescription[] =
2003 "SYN_STREAM frame, low pri, no FIN";
2005 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2006 const unsigned char kV2FrameData[] = {
2007 0x80, spdy_version_ch_, 0x00, 0x01,
2008 0x00, 0x00, 0x00, 0x36,
2009 0x00, 0x00, 0x00, 0x01,
2010 0x00, 0x00, 0x00, 0x00,
2011 0x80, 0x00, 0x38, 0xea,
2012 0xdf, 0xa2, 0x51, 0xb2,
2013 0x62, 0x60, 0x62, 0x60,
2014 0x4e, 0x4a, 0x2c, 0x62,
2015 0x60, 0x06, 0x08, 0xa0,
2016 0xb4, 0xfc, 0x7c, 0x80,
2017 0x00, 0x62, 0x60, 0x4e,
2018 0xcb, 0xcf, 0x67, 0x60,
2019 0x06, 0x08, 0xa0, 0xa4,
2020 0xc4, 0x22, 0x80, 0x00,
2021 0x02, 0x00, 0x00, 0x00,
2022 0xff, 0xff,
2024 const unsigned char kV3FrameData[] = {
2025 0x80, spdy_version_ch_, 0x00, 0x01,
2026 0x00, 0x00, 0x00, 0x37,
2027 0x00, 0x00, 0x00, 0x01,
2028 0x00, 0x00, 0x00, 0x00,
2029 0x80, 0x00, 0x38, 0xEA,
2030 0xE3, 0xC6, 0xA7, 0xC2,
2031 0x02, 0xE5, 0x0E, 0x50,
2032 0xC2, 0x4B, 0x4A, 0x04,
2033 0xE5, 0x0B, 0x66, 0x80,
2034 0x00, 0x4A, 0xCB, 0xCF,
2035 0x07, 0x08, 0x20, 0x10,
2036 0x95, 0x96, 0x9F, 0x0F,
2037 0xA2, 0x00, 0x02, 0x28,
2038 0x29, 0xB1, 0x08, 0x20,
2039 0x80, 0x00, 0x00, 0x00,
2040 0x00, 0xFF, 0xFF,
2042 SpdySynStreamIR syn_stream(1);
2043 syn_stream.set_priority(priority);
2044 syn_stream.SetHeader("bar", "foo");
2045 syn_stream.SetHeader("foo", "bar");
2046 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2047 if (IsSpdy2()) {
2048 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2049 } else if (IsSpdy3()) {
2050 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2051 } else {
2052 // Deflate compression doesn't apply to HPACK.
2056 #endif // !defined(USE_SYSTEM_ZLIB)
2058 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2059 SpdyFramer framer(spdy_version_);
2060 framer.set_enable_compression(false);
2063 const char kDescription[] = "SYN_REPLY frame, no FIN";
2065 const unsigned char kV2FrameData[] = {
2066 0x80, spdy_version_ch_, 0x00, 0x02,
2067 0x00, 0x00, 0x00, 0x1C,
2068 0x00, 0x00, 0x00, 0x01,
2069 0x00, 0x00, 0x00, 0x02,
2070 0x00, 0x03, 'b', 'a',
2071 'r', 0x00, 0x03, 'f',
2072 'o', 'o', 0x00, 0x03,
2073 'f', 'o', 'o', 0x00,
2074 0x03, 'b', 'a', 'r'
2076 const unsigned char kV3FrameData[] = {
2077 0x80, spdy_version_ch_, 0x00, 0x02,
2078 0x00, 0x00, 0x00, 0x24,
2079 0x00, 0x00, 0x00, 0x01,
2080 0x00, 0x00, 0x00, 0x02,
2081 0x00, 0x00, 0x00, 0x03,
2082 'b', 'a', 'r', 0x00,
2083 0x00, 0x00, 0x03, 'f',
2084 'o', 'o', 0x00, 0x00,
2085 0x00, 0x03, 'f', 'o',
2086 'o', 0x00, 0x00, 0x00,
2087 0x03, 'b', 'a', 'r'
2089 const unsigned char kV4FrameData[] = {
2090 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
2091 0x00, 0x00, 0x00, 0x01, // Stream 1
2092 0x40, 0x03, 0x62, 0x61, // @.ba
2093 0x72, 0x03, 0x66, 0x6f, // r.fo
2094 0x6f, 0x40, 0x03, 0x66, // o@.f
2095 0x6f, 0x6f, 0x03, 0x62, // oo.b
2096 0x61, 0x72, // ar
2098 SpdySynReplyIR syn_reply(1);
2099 syn_reply.SetHeader("bar", "foo");
2100 syn_reply.SetHeader("foo", "bar");
2101 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2102 if (IsSpdy2()) {
2103 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2104 } else if (IsSpdy3()) {
2105 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2106 } else {
2107 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2112 const char kDescription[] =
2113 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2115 const unsigned char kV2FrameData[] = {
2116 0x80, spdy_version_ch_, 0x00, 0x02,
2117 0x01, 0x00, 0x00, 0x19,
2118 0x7f, 0xff, 0xff, 0xff,
2119 0x00, 0x00, 0x00, 0x02,
2120 0x00, 0x00, 0x00, 0x03,
2121 'f', 'o', 'o', 0x00,
2122 0x03, 'f', 'o', 'o',
2123 0x00, 0x03, 'b', 'a',
2126 const unsigned char kV3FrameData[] = {
2127 0x80, spdy_version_ch_, 0x00, 0x02,
2128 0x01, 0x00, 0x00, 0x21,
2129 0x7f, 0xff, 0xff, 0xff,
2130 0x00, 0x00, 0x00, 0x02,
2131 0x00, 0x00, 0x00, 0x00,
2132 0x00, 0x00, 0x00, 0x03,
2133 'f', 'o', 'o', 0x00,
2134 0x00, 0x00, 0x03, 'f',
2135 'o', 'o', 0x00, 0x00,
2136 0x00, 0x03, 'b', 'a',
2139 const unsigned char kV4FrameData[] = {
2140 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2141 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2142 0x40, 0x00, 0x03, 0x66, // @..f
2143 0x6f, 0x6f, 0x40, 0x03, // oo@.
2144 0x66, 0x6f, 0x6f, 0x03, // foo.
2145 0x62, 0x61, 0x72, // bar
2147 SpdySynReplyIR syn_reply(0x7fffffff);
2148 syn_reply.set_fin(true);
2149 syn_reply.SetHeader("", "foo");
2150 syn_reply.SetHeader("foo", "bar");
2151 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2152 if (IsSpdy2()) {
2153 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2154 } else if (IsSpdy3()) {
2155 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2156 } else {
2157 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2162 const char kDescription[] =
2163 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2165 const unsigned char kV2FrameData[] = {
2166 0x80, spdy_version_ch_, 0x00, 0x02,
2167 0x01, 0x00, 0x00, 0x19,
2168 0x7f, 0xff, 0xff, 0xff,
2169 0x00, 0x00, 0x00, 0x02,
2170 0x00, 0x03, 'b', 'a',
2171 'r', 0x00, 0x03, 'f',
2172 'o', 'o', 0x00, 0x03,
2173 'f', 'o', 'o', 0x00,
2174 0x00
2176 const unsigned char kV3FrameData[] = {
2177 0x80, spdy_version_ch_, 0x00, 0x02,
2178 0x01, 0x00, 0x00, 0x21,
2179 0x7f, 0xff, 0xff, 0xff,
2180 0x00, 0x00, 0x00, 0x02,
2181 0x00, 0x00, 0x00, 0x03,
2182 'b', 'a', 'r', 0x00,
2183 0x00, 0x00, 0x03, 'f',
2184 'o', 'o', 0x00, 0x00,
2185 0x00, 0x03, 'f', 'o',
2186 'o', 0x00, 0x00, 0x00,
2187 0x00
2189 const unsigned char kV4FrameData[] = {
2190 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2191 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2192 0x40, 0x03, 0x62, 0x61, // @.ba
2193 0x72, 0x03, 0x66, 0x6f, // r.fo
2194 0x6f, 0x40, 0x03, 0x66, // o@.f
2195 0x6f, 0x6f, 0x00, // oo.
2197 SpdySynReplyIR syn_reply(0x7fffffff);
2198 syn_reply.set_fin(true);
2199 syn_reply.SetHeader("bar", "foo");
2200 syn_reply.SetHeader("foo", "");
2201 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2202 if (IsSpdy2()) {
2203 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2204 } else if (IsSpdy3()) {
2205 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2206 } else {
2207 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2212 // TODO(phajdan.jr): Clean up after we no longer need
2213 // to workaround http://crbug.com/139744.
2214 #if !defined(USE_SYSTEM_ZLIB)
2215 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2216 SpdyFramer framer(spdy_version_);
2217 framer.set_enable_compression(true);
2220 const char kDescription[] = "SYN_REPLY frame, no FIN";
2222 const unsigned char kV2FrameData[] = {
2223 0x80, spdy_version_ch_, 0x00, 0x02,
2224 0x00, 0x00, 0x00, 0x32,
2225 0x00, 0x00, 0x00, 0x01,
2226 0x00, 0x00, 0x38, 0xea,
2227 0xdf, 0xa2, 0x51, 0xb2,
2228 0x62, 0x60, 0x62, 0x60,
2229 0x4e, 0x4a, 0x2c, 0x62,
2230 0x60, 0x06, 0x08, 0xa0,
2231 0xb4, 0xfc, 0x7c, 0x80,
2232 0x00, 0x62, 0x60, 0x4e,
2233 0xcb, 0xcf, 0x67, 0x60,
2234 0x06, 0x08, 0xa0, 0xa4,
2235 0xc4, 0x22, 0x80, 0x00,
2236 0x02, 0x00, 0x00, 0x00,
2237 0xff, 0xff,
2239 const unsigned char kV3FrameData[] = {
2240 0x80, spdy_version_ch_, 0x00, 0x02,
2241 0x00, 0x00, 0x00, 0x31,
2242 0x00, 0x00, 0x00, 0x01,
2243 0x38, 0xea, 0xe3, 0xc6,
2244 0xa7, 0xc2, 0x02, 0xe5,
2245 0x0e, 0x50, 0xc2, 0x4b,
2246 0x4a, 0x04, 0xe5, 0x0b,
2247 0x66, 0x80, 0x00, 0x4a,
2248 0xcb, 0xcf, 0x07, 0x08,
2249 0x20, 0x10, 0x95, 0x96,
2250 0x9f, 0x0f, 0xa2, 0x00,
2251 0x02, 0x28, 0x29, 0xb1,
2252 0x08, 0x20, 0x80, 0x00,
2253 0x00, 0x00, 0x00, 0xff,
2254 0xff,
2256 SpdySynReplyIR syn_reply(1);
2257 syn_reply.SetHeader("bar", "foo");
2258 syn_reply.SetHeader("foo", "bar");
2259 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2260 if (IsSpdy2()) {
2261 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2262 } else if (IsSpdy3()) {
2263 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2264 } else {
2265 // Deflate compression doesn't apply to HPACK.
2269 #endif // !defined(USE_SYSTEM_ZLIB)
2271 TEST_P(SpdyFramerTest, CreateRstStream) {
2272 SpdyFramer framer(spdy_version_);
2275 const char kDescription[] = "RST_STREAM frame";
2276 const unsigned char kV3FrameData[] = { // Also applies for V2.
2277 0x80, spdy_version_ch_, 0x00, 0x03,
2278 0x00, 0x00, 0x00, 0x08,
2279 0x00, 0x00, 0x00, 0x01,
2280 0x00, 0x00, 0x00, 0x01,
2282 const unsigned char kV4FrameData[] = {
2283 0x00, 0x07, 0x03, 0x00,
2284 0x00, 0x00, 0x00, 0x01,
2285 0x00, 0x00, 0x00, 0x01,
2286 0x52, 0x53, 0x54
2288 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2289 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2290 if (IsSpdy4()) {
2291 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2292 } else {
2293 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2298 const char kDescription[] = "RST_STREAM frame with max stream ID";
2299 const unsigned char kV3FrameData[] = { // Also applies for V2.
2300 0x80, spdy_version_ch_, 0x00, 0x03,
2301 0x00, 0x00, 0x00, 0x08,
2302 0x7f, 0xff, 0xff, 0xff,
2303 0x00, 0x00, 0x00, 0x01,
2305 const unsigned char kV4FrameData[] = {
2306 0x00, 0x04, 0x03, 0x00,
2307 0x7f, 0xff, 0xff, 0xff,
2308 0x00, 0x00, 0x00, 0x01,
2310 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2311 RST_STREAM_PROTOCOL_ERROR,
2312 "");
2313 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2314 if (IsSpdy4()) {
2315 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2316 } else {
2317 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2322 const char kDescription[] = "RST_STREAM frame with max status code";
2323 const unsigned char kV3FrameData[] = { // Also applies for V2.
2324 0x80, spdy_version_ch_, 0x00, 0x03,
2325 0x00, 0x00, 0x00, 0x08,
2326 0x7f, 0xff, 0xff, 0xff,
2327 0x00, 0x00, 0x00, 0x06,
2329 const unsigned char kV4FrameData[] = {
2330 0x00, 0x04, 0x03, 0x00,
2331 0x7f, 0xff, 0xff, 0xff,
2332 0x00, 0x00, 0x00, 0x06,
2334 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2335 RST_STREAM_INTERNAL_ERROR,
2336 "");
2337 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2338 if (IsSpdy4()) {
2339 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2340 } else {
2341 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2346 TEST_P(SpdyFramerTest, CreateSettings) {
2347 SpdyFramer framer(spdy_version_);
2350 const char kDescription[] = "Network byte order SETTINGS frame";
2352 const unsigned char kV2FrameData[] = {
2353 0x80, spdy_version_ch_, 0x00, 0x04,
2354 0x00, 0x00, 0x00, 0x0c,
2355 0x00, 0x00, 0x00, 0x01,
2356 0x07, 0x00, 0x00, 0x01,
2357 0x0a, 0x0b, 0x0c, 0x0d,
2359 const unsigned char kV3FrameData[] = {
2360 0x80, spdy_version_ch_, 0x00, 0x04,
2361 0x00, 0x00, 0x00, 0x0c,
2362 0x00, 0x00, 0x00, 0x01,
2363 0x01, 0x00, 0x00, 0x07,
2364 0x0a, 0x0b, 0x0c, 0x0d,
2366 const unsigned char kV4FrameData[] = {
2367 0x00, 0x05, 0x04, 0x00,
2368 0x00, 0x00, 0x00, 0x00,
2369 0x04, 0x0a, 0x0b, 0x0c,
2370 0x0d,
2373 uint32 kValue = 0x0a0b0c0d;
2374 SpdySettingsIR settings_ir;
2376 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2377 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2378 SettingsMap settings;
2379 settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
2380 EXPECT_EQ(kFlags, settings[kId].first);
2381 EXPECT_EQ(kValue, settings[kId].second);
2382 settings_ir.AddSetting(kId,
2383 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2384 kFlags & SETTINGS_FLAG_PERSISTED,
2385 kValue);
2387 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2388 if (IsSpdy2()) {
2389 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2390 } else if (IsSpdy3()) {
2391 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2392 } else {
2393 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2398 const char kDescription[] = "Basic SETTINGS frame";
2400 const unsigned char kV2FrameData[] = {
2401 0x80, spdy_version_ch_, 0x00, 0x04,
2402 0x00, 0x00, 0x00, 0x24,
2403 0x00, 0x00, 0x00, 0x04,
2404 0x01, 0x00, 0x00, 0x00, // 1st Setting
2405 0x00, 0x00, 0x00, 0x05,
2406 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2407 0x00, 0x00, 0x00, 0x06,
2408 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2409 0x00, 0x00, 0x00, 0x07,
2410 0x04, 0x00, 0x00, 0x00, // 4th Setting
2411 0x00, 0x00, 0x00, 0x08,
2413 const unsigned char kV3FrameData[] = {
2414 0x80, spdy_version_ch_, 0x00, 0x04,
2415 0x00, 0x00, 0x00, 0x24,
2416 0x00, 0x00, 0x00, 0x04,
2417 0x00, 0x00, 0x00, 0x01, // 1st Setting
2418 0x00, 0x00, 0x00, 0x05,
2419 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2420 0x00, 0x00, 0x00, 0x06,
2421 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2422 0x00, 0x00, 0x00, 0x07,
2423 0x00, 0x00, 0x00, 0x04, // 4th Setting
2424 0x00, 0x00, 0x00, 0x08,
2426 // These end up seemingly out of order because of the way that our internal
2427 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2428 // the wire.
2429 const unsigned char kV4FrameData[] = {
2430 0x00, 0x14, 0x04, 0x00,
2431 0x00, 0x00, 0x00, 0x00,
2432 0x03, // 3rd Setting
2433 0x00, 0x00, 0x00, 0x07,
2434 0x04, // 4th Setting
2435 0x00, 0x00, 0x00, 0x08,
2436 0x01, // 1st Setting
2437 0x00, 0x00, 0x00, 0x05,
2438 0x02, // 2nd Setting
2439 0x00, 0x00, 0x00, 0x06,
2442 SpdySettingsIR settings_ir;
2443 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2444 false, // persist
2445 false, // persisted
2447 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2448 false, // persist
2449 false, // persisted
2451 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2452 false, // persist
2453 false, // persisted
2455 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2456 false, // persist
2457 false, // persisted
2459 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2461 if (IsSpdy2()) {
2462 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2463 } else if (IsSpdy3()) {
2464 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2465 } else {
2466 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2471 const char kDescription[] = "Empty SETTINGS frame";
2473 const unsigned char kV3FrameData[] = { // Also applies for V2.
2474 0x80, spdy_version_ch_, 0x00, 0x04,
2475 0x00, 0x00, 0x00, 0x04,
2476 0x00, 0x00, 0x00, 0x00,
2478 const unsigned char kV4FrameData[] = {
2479 0x00, 0x00, 0x04, 0x00,
2480 0x00, 0x00, 0x00, 0x00,
2482 SpdySettingsIR settings_ir;
2483 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2484 if (IsSpdy4()) {
2485 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2486 } else {
2487 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2492 TEST_P(SpdyFramerTest, CreatePingFrame) {
2493 SpdyFramer framer(spdy_version_);
2496 const char kDescription[] = "PING frame";
2497 const unsigned char kV3FrameData[] = { // Also applies for V2.
2498 0x80, spdy_version_ch_, 0x00, 0x06,
2499 0x00, 0x00, 0x00, 0x04,
2500 0x12, 0x34, 0x56, 0x78,
2502 const unsigned char kV4FrameData[] = {
2503 0x00, 0x08, 0x06, 0x00,
2504 0x00, 0x00, 0x00, 0x00,
2505 0x12, 0x34, 0x56, 0x78,
2506 0x9a, 0xbc, 0xde, 0xff,
2508 const unsigned char kV4FrameDataWithAck[] = {
2509 0x00, 0x08, 0x06, 0x01,
2510 0x00, 0x00, 0x00, 0x00,
2511 0x12, 0x34, 0x56, 0x78,
2512 0x9a, 0xbc, 0xde, 0xff,
2514 scoped_ptr<SpdyFrame> frame;
2515 if (IsSpdy4()) {
2516 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2517 SpdyPingIR ping_ir(kPingId);
2518 // Tests SpdyPingIR when the ping is not an ack.
2519 ASSERT_FALSE(ping_ir.is_ack());
2520 frame.reset(framer.SerializePing(ping_ir));
2521 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2523 // Tests SpdyPingIR when the ping is an ack.
2524 ping_ir.set_is_ack(true);
2525 frame.reset(framer.SerializePing(ping_ir));
2526 CompareFrame(kDescription, *frame,
2527 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2529 } else {
2530 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2531 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2536 TEST_P(SpdyFramerTest, CreateGoAway) {
2537 SpdyFramer framer(spdy_version_);
2540 const char kDescription[] = "GOAWAY frame";
2541 const unsigned char kV2FrameData[] = {
2542 0x80, spdy_version_ch_, 0x00, 0x07,
2543 0x00, 0x00, 0x00, 0x04,
2544 0x00, 0x00, 0x00, 0x00, // Stream Id
2546 const unsigned char kV3FrameData[] = {
2547 0x80, spdy_version_ch_, 0x00, 0x07,
2548 0x00, 0x00, 0x00, 0x08,
2549 0x00, 0x00, 0x00, 0x00, // Stream Id
2550 0x00, 0x00, 0x00, 0x00, // Status
2552 const unsigned char kV4FrameData[] = {
2553 0x00, 0x0a, 0x07, 0x00,
2554 0x00, 0x00, 0x00, 0x00,
2555 0x00, 0x00, 0x00, 0x00, // Stream id
2556 0x00, 0x00, 0x00, 0x00, // Status
2557 0x47, 0x41, // Opaque Description
2559 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2560 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2561 if (IsSpdy2()) {
2562 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2563 } else if (IsSpdy3()) {
2564 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2565 } else {
2566 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2571 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2572 const unsigned char kV2FrameData[] = {
2573 0x80, spdy_version_ch_, 0x00, 0x07,
2574 0x00, 0x00, 0x00, 0x04,
2575 0x7f, 0xff, 0xff, 0xff, // Stream Id
2577 const unsigned char kV3FrameData[] = {
2578 0x80, spdy_version_ch_, 0x00, 0x07,
2579 0x00, 0x00, 0x00, 0x08,
2580 0x7f, 0xff, 0xff, 0xff, // Stream Id
2581 0x00, 0x00, 0x00, 0x02, // Status
2583 const unsigned char kV4FrameData[] = {
2584 0x00, 0x0a, 0x07, 0x00,
2585 0x00, 0x00, 0x00, 0x00,
2586 0x7f, 0xff, 0xff, 0xff, // Stream Id
2587 0x00, 0x00, 0x00, 0x02, // Status
2588 0x47, 0x41, // Opaque Description
2590 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2591 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2592 if (IsSpdy2()) {
2593 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2594 } else if (IsSpdy3()) {
2595 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2596 } else {
2597 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2602 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2603 SpdyFramer framer(spdy_version_);
2604 framer.set_enable_compression(false);
2607 const char kDescription[] = "HEADERS frame, no FIN";
2609 const unsigned char kV2FrameData[] = {
2610 0x80, spdy_version_ch_, 0x00, 0x08,
2611 0x00, 0x00, 0x00, 0x1C,
2612 0x00, 0x00, 0x00, 0x01,
2613 0x00, 0x00, 0x00, 0x02,
2614 0x00, 0x03, 'b', 'a',
2615 'r', 0x00, 0x03, 'f',
2616 'o', 'o', 0x00, 0x03,
2617 'f', 'o', 'o', 0x00,
2618 0x03, 'b', 'a', 'r'
2620 const unsigned char kV3FrameData[] = {
2621 0x80, spdy_version_ch_, 0x00, 0x08,
2622 0x00, 0x00, 0x00, 0x24,
2623 0x00, 0x00, 0x00, 0x01,
2624 0x00, 0x00, 0x00, 0x02,
2625 0x00, 0x00, 0x00, 0x03,
2626 'b', 'a', 'r', 0x00,
2627 0x00, 0x00, 0x03, 'f',
2628 'o', 'o', 0x00, 0x00,
2629 0x00, 0x03, 'f', 'o',
2630 'o', 0x00, 0x00, 0x00,
2631 0x03, 'b', 'a', 'r'
2633 const unsigned char kV4FrameData[] = {
2634 0x00, 0x12, 0x01, 0x04, // Headers: END_HEADERS
2635 0x00, 0x00, 0x00, 0x01, // Stream 1
2636 0x40, 0x03, 0x62, 0x61, // @.ba
2637 0x72, 0x03, 0x66, 0x6f, // r.fo
2638 0x6f, 0x40, 0x03, 0x66, // o@.f
2639 0x6f, 0x6f, 0x03, 0x62, // oo.b
2640 0x61, 0x72, // ar
2642 SpdyHeadersIR headers_ir(1);
2643 headers_ir.SetHeader("bar", "foo");
2644 headers_ir.SetHeader("foo", "bar");
2645 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2646 if (IsSpdy2()) {
2647 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2648 } else if (IsSpdy3()) {
2649 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2650 } else {
2651 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2656 const char kDescription[] =
2657 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2659 const unsigned char kV2FrameData[] = {
2660 0x80, spdy_version_ch_, 0x00, 0x08,
2661 0x01, 0x00, 0x00, 0x19,
2662 0x7f, 0xff, 0xff, 0xff,
2663 0x00, 0x00, 0x00, 0x02,
2664 0x00, 0x00, 0x00, 0x03,
2665 'f', 'o', 'o', 0x00,
2666 0x03, 'f', 'o', 'o',
2667 0x00, 0x03, 'b', 'a',
2670 const unsigned char kV3FrameData[] = {
2671 0x80, spdy_version_ch_, 0x00, 0x08,
2672 0x01, 0x00, 0x00, 0x21,
2673 0x7f, 0xff, 0xff, 0xff,
2674 0x00, 0x00, 0x00, 0x02,
2675 0x00, 0x00, 0x00, 0x00,
2676 0x00, 0x00, 0x00, 0x03,
2677 'f', 'o', 'o', 0x00,
2678 0x00, 0x00, 0x03, 'f',
2679 'o', 'o', 0x00, 0x00,
2680 0x00, 0x03, 'b', 'a',
2683 const unsigned char kV4FrameData[] = {
2684 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2685 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2686 0x40, 0x00, 0x03, 0x66, // @..f
2687 0x6f, 0x6f, 0x40, 0x03, // oo@.
2688 0x66, 0x6f, 0x6f, 0x03, // foo.
2689 0x62, 0x61, 0x72, // bar
2691 SpdyHeadersIR headers_ir(0x7fffffff);
2692 headers_ir.set_fin(true);
2693 headers_ir.SetHeader("", "foo");
2694 headers_ir.SetHeader("foo", "bar");
2695 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2696 if (IsSpdy2()) {
2697 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2698 } else if (IsSpdy3()) {
2699 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2700 } else {
2701 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2706 const char kDescription[] =
2707 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2709 const unsigned char kV2FrameData[] = {
2710 0x80, spdy_version_ch_, 0x00, 0x08,
2711 0x01, 0x00, 0x00, 0x19,
2712 0x7f, 0xff, 0xff, 0xff,
2713 0x00, 0x00, 0x00, 0x02,
2714 0x00, 0x03, 'b', 'a',
2715 'r', 0x00, 0x03, 'f',
2716 'o', 'o', 0x00, 0x03,
2717 'f', 'o', 'o', 0x00,
2718 0x00
2720 const unsigned char kV3FrameData[] = {
2721 0x80, spdy_version_ch_, 0x00, 0x08,
2722 0x01, 0x00, 0x00, 0x21,
2723 0x7f, 0xff, 0xff, 0xff,
2724 0x00, 0x00, 0x00, 0x02,
2725 0x00, 0x00, 0x00, 0x03,
2726 'b', 'a', 'r', 0x00,
2727 0x00, 0x00, 0x03, 'f',
2728 'o', 'o', 0x00, 0x00,
2729 0x00, 0x03, 'f', 'o',
2730 'o', 0x00, 0x00, 0x00,
2731 0x00
2733 const unsigned char kV4FrameData[] = {
2734 0x00, 0x0f, 0x01, 0x05, // HEADER: FIN | END_HEADERS
2735 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff
2736 0x40, 0x03, 0x62, 0x61, // @.ba
2737 0x72, 0x03, 0x66, 0x6f, // r.fo
2738 0x6f, 0x40, 0x03, 0x66, // o@.f
2739 0x6f, 0x6f, 0x00, // oo.
2741 SpdyHeadersIR headers_ir(0x7fffffff);
2742 headers_ir.set_fin(true);
2743 headers_ir.SetHeader("bar", "foo");
2744 headers_ir.SetHeader("foo", "");
2745 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2746 if (IsSpdy2()) {
2747 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2748 } else if (IsSpdy3()) {
2749 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2750 } else {
2751 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2756 // TODO(phajdan.jr): Clean up after we no longer need
2757 // to workaround http://crbug.com/139744.
2758 #if !defined(USE_SYSTEM_ZLIB)
2759 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2760 SpdyFramer framer(spdy_version_);
2761 framer.set_enable_compression(true);
2764 const char kDescription[] = "HEADERS frame, no FIN";
2766 const unsigned char kV2FrameData[] = {
2767 0x80, spdy_version_ch_, 0x00, 0x08,
2768 0x00, 0x00, 0x00, 0x32,
2769 0x00, 0x00, 0x00, 0x01,
2770 0x00, 0x00, 0x38, 0xea,
2771 0xdf, 0xa2, 0x51, 0xb2,
2772 0x62, 0x60, 0x62, 0x60,
2773 0x4e, 0x4a, 0x2c, 0x62,
2774 0x60, 0x06, 0x08, 0xa0,
2775 0xb4, 0xfc, 0x7c, 0x80,
2776 0x00, 0x62, 0x60, 0x4e,
2777 0xcb, 0xcf, 0x67, 0x60,
2778 0x06, 0x08, 0xa0, 0xa4,
2779 0xc4, 0x22, 0x80, 0x00,
2780 0x02, 0x00, 0x00, 0x00,
2781 0xff, 0xff,
2783 const unsigned char kV3FrameData[] = {
2784 0x80, spdy_version_ch_, 0x00, 0x08,
2785 0x00, 0x00, 0x00, 0x31,
2786 0x00, 0x00, 0x00, 0x01,
2787 0x38, 0xea, 0xe3, 0xc6,
2788 0xa7, 0xc2, 0x02, 0xe5,
2789 0x0e, 0x50, 0xc2, 0x4b,
2790 0x4a, 0x04, 0xe5, 0x0b,
2791 0x66, 0x80, 0x00, 0x4a,
2792 0xcb, 0xcf, 0x07, 0x08,
2793 0x20, 0x10, 0x95, 0x96,
2794 0x9f, 0x0f, 0xa2, 0x00,
2795 0x02, 0x28, 0x29, 0xb1,
2796 0x08, 0x20, 0x80, 0x00,
2797 0x00, 0x00, 0x00, 0xff,
2798 0xff,
2800 SpdyHeadersIR headers_ir(1);
2801 headers_ir.SetHeader("bar", "foo");
2802 headers_ir.SetHeader("foo", "bar");
2803 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2804 if (IsSpdy2()) {
2805 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2806 } else if (IsSpdy3()) {
2807 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2808 } else {
2809 // Deflate compression doesn't apply to HPACK.
2813 #endif // !defined(USE_SYSTEM_ZLIB)
2815 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
2816 SpdyFramer framer(spdy_version_);
2819 const char kDescription[] = "WINDOW_UPDATE frame";
2820 const unsigned char kV3FrameData[] = { // Also applies for V2.
2821 0x80, spdy_version_ch_, 0x00, 0x09,
2822 0x00, 0x00, 0x00, 0x08,
2823 0x00, 0x00, 0x00, 0x01,
2824 0x00, 0x00, 0x00, 0x01,
2826 const unsigned char kV4FrameData[] = {
2827 0x00, 0x04, 0x08, 0x00,
2828 0x00, 0x00, 0x00, 0x01,
2829 0x00, 0x00, 0x00, 0x01,
2831 scoped_ptr<SpdyFrame> frame(
2832 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
2833 if (IsSpdy4()) {
2834 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2835 } else {
2836 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2841 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
2842 const unsigned char kV3FrameData[] = { // Also applies for V2.
2843 0x80, spdy_version_ch_, 0x00, 0x09,
2844 0x00, 0x00, 0x00, 0x08,
2845 0x7f, 0xff, 0xff, 0xff,
2846 0x00, 0x00, 0x00, 0x01,
2848 const unsigned char kV4FrameData[] = {
2849 0x00, 0x04, 0x08, 0x00,
2850 0x7f, 0xff, 0xff, 0xff,
2851 0x00, 0x00, 0x00, 0x01,
2853 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2854 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2855 if (IsSpdy4()) {
2856 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2857 } else {
2858 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2863 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
2864 const unsigned char kV3FrameData[] = { // Also applies for V2.
2865 0x80, spdy_version_ch_, 0x00, 0x09,
2866 0x00, 0x00, 0x00, 0x08,
2867 0x00, 0x00, 0x00, 0x01,
2868 0x7f, 0xff, 0xff, 0xff,
2870 const unsigned char kV4FrameData[] = {
2871 0x00, 0x04, 0x08, 0x00,
2872 0x00, 0x00, 0x00, 0x01,
2873 0x7f, 0xff, 0xff, 0xff,
2875 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2876 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2877 if (IsSpdy4()) {
2878 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2879 } else {
2880 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2885 TEST_P(SpdyFramerTest, SerializeBlocked) {
2886 if (spdy_version_ < SPDY4) {
2887 return;
2890 SpdyFramer framer(spdy_version_);
2892 const char kDescription[] = "BLOCKED frame";
2893 const unsigned char kFrameData[] = {
2894 0x00, 0x00, 0x0a, 0x00,
2895 0x00, 0x00, 0x00, 0x00,
2897 SpdyBlockedIR blocked_ir(0);
2898 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
2899 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2902 TEST_P(SpdyFramerTest, CreateBlocked) {
2903 if (spdy_version_ < SPDY4) {
2904 return;
2907 SpdyFramer framer(spdy_version_);
2909 const char kDescription[] = "BLOCKED frame";
2910 const SpdyStreamId kStreamId = 3;
2912 scoped_ptr<SpdySerializedFrame> frame_serialized(
2913 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
2914 SpdyBlockedIR blocked_ir(kStreamId);
2915 scoped_ptr<SpdySerializedFrame> frame_created(
2916 framer.SerializeFrame(blocked_ir));
2918 CompareFrames(kDescription, *frame_serialized, *frame_created);
2921 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
2922 if (spdy_version_ < SPDY4) {
2923 return;
2926 SpdyFramer framer(spdy_version_);
2927 framer.set_enable_compression(false);
2928 const char kDescription[] = "PUSH_PROMISE frame";
2930 const unsigned char kFrameData[] = {
2931 0x00, 0x16, 0x05, 0x04, // PUSH_PROMISE: END_HEADERS
2932 0x00, 0x00, 0x00, 0x2a, // Stream 42
2933 0x00, 0x00, 0x00, 0x39, // Promised stream 57
2934 0x40, 0x03, 0x62, 0x61, // @.ba
2935 0x72, 0x03, 0x66, 0x6f, // r.fo
2936 0x6f, 0x40, 0x03, 0x66, // o@.f
2937 0x6f, 0x6f, 0x03, 0x62, // oo.b
2938 0x61, 0x72, // ar
2941 SpdyPushPromiseIR push_promise(42, 57);
2942 push_promise.SetHeader("bar", "foo");
2943 push_promise.SetHeader("foo", "bar");
2944 scoped_ptr<SpdySerializedFrame> frame(
2945 framer.SerializePushPromise(push_promise));
2946 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2949 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
2950 SpdyFramer framer(spdy_version_);
2951 SpdySynStreamIR syn_stream(1);
2952 syn_stream.set_priority(1);
2953 syn_stream.SetHeader("aa", "vv");
2954 syn_stream.SetHeader("bb", "ww");
2955 SpdyHeaderBlock headers = syn_stream.name_value_block();
2956 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
2957 EXPECT_TRUE(control_frame.get() != NULL);
2958 TestSpdyVisitor visitor(spdy_version_);
2959 visitor.use_compression_ = true;
2960 visitor.SimulateInFramer(
2961 reinterpret_cast<unsigned char*>(control_frame->data()),
2962 control_frame->size());
2963 EXPECT_EQ(1, visitor.syn_frame_count_);
2964 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
2967 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
2968 SpdyFramer framer(spdy_version_);
2969 SpdySynReplyIR syn_reply(1);
2970 syn_reply.SetHeader("alpha", "beta");
2971 syn_reply.SetHeader("gamma", "delta");
2972 SpdyHeaderBlock headers = syn_reply.name_value_block();
2973 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
2974 EXPECT_TRUE(control_frame.get() != NULL);
2975 TestSpdyVisitor visitor(spdy_version_);
2976 visitor.use_compression_ = true;
2977 visitor.SimulateInFramer(
2978 reinterpret_cast<unsigned char*>(control_frame->data()),
2979 control_frame->size());
2980 if (IsSpdy4()) {
2981 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
2982 EXPECT_EQ(1, visitor.headers_frame_count_);
2983 } else {
2984 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
2985 EXPECT_EQ(0, visitor.headers_frame_count_);
2987 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
2990 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
2991 SpdyFramer framer(spdy_version_);
2992 SpdyHeadersIR headers_ir(1);
2993 headers_ir.SetHeader("alpha", "beta");
2994 headers_ir.SetHeader("gamma", "delta");
2995 SpdyHeaderBlock headers = headers_ir.name_value_block();
2996 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
2997 EXPECT_TRUE(control_frame.get() != NULL);
2998 TestSpdyVisitor visitor(spdy_version_);
2999 visitor.use_compression_ = true;
3000 visitor.SimulateInFramer(
3001 reinterpret_cast<unsigned char*>(control_frame->data()),
3002 control_frame->size());
3003 EXPECT_EQ(1, visitor.headers_frame_count_);
3004 // control_frame_header_data_count_ depends on the random sequence
3005 // produced by rand(), so adding, removing or running single tests
3006 // alters this value. The best we can do is assert that it happens
3007 // at least twice.
3008 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3009 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3010 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3011 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3014 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3015 SpdyFramer framer(spdy_version_);
3016 SpdyHeadersIR headers_ir(1);
3017 headers_ir.set_fin(true);
3018 headers_ir.SetHeader("alpha", "beta");
3019 headers_ir.SetHeader("gamma", "delta");
3020 SpdyHeaderBlock headers = headers_ir.name_value_block();
3021 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3022 EXPECT_TRUE(control_frame.get() != NULL);
3023 TestSpdyVisitor visitor(spdy_version_);
3024 visitor.use_compression_ = true;
3025 visitor.SimulateInFramer(
3026 reinterpret_cast<unsigned char*>(control_frame->data()),
3027 control_frame->size());
3028 EXPECT_EQ(1, visitor.headers_frame_count_);
3029 // control_frame_header_data_count_ depends on the random sequence
3030 // produced by rand(), so adding, removing or running single tests
3031 // alters this value. The best we can do is assert that it happens
3032 // at least twice.
3033 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3034 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3035 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3036 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3039 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3040 if (spdy_version_ > SPDY3) {
3041 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3042 return;
3044 // First find the size of the header value in order to just reach the control
3045 // frame max size.
3046 SpdyFramer framer(spdy_version_);
3047 framer.set_enable_compression(false);
3048 SpdySynStreamIR syn_stream(1);
3049 syn_stream.set_priority(1);
3050 syn_stream.SetHeader("aa", "");
3051 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3052 const size_t kBigValueSize =
3053 framer.GetControlFrameBufferMaxSize() - control_frame->size();
3055 // Create a frame at exactly that size.
3056 string big_value(kBigValueSize, 'x');
3057 syn_stream.SetHeader("aa", big_value.c_str());
3058 control_frame.reset(framer.SerializeSynStream(syn_stream));
3059 EXPECT_TRUE(control_frame.get() != NULL);
3060 EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size());
3062 TestSpdyVisitor visitor(spdy_version_);
3063 visitor.SimulateInFramer(
3064 reinterpret_cast<unsigned char*>(control_frame->data()),
3065 control_frame->size());
3066 EXPECT_TRUE(visitor.header_buffer_valid_);
3067 EXPECT_EQ(0, visitor.error_count_);
3068 EXPECT_EQ(1, visitor.syn_frame_count_);
3069 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3070 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3071 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3074 TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
3075 if (spdy_version_ > SPDY3) {
3076 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3077 return;
3079 // First find the size of the header value in order to just reach the control
3080 // frame max size.
3081 SpdyFramer framer(spdy_version_);
3082 framer.set_enable_compression(false);
3083 SpdySynStreamIR syn_stream(1);
3084 syn_stream.SetHeader("aa", "");
3085 syn_stream.set_priority(1);
3086 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3087 const size_t kBigValueSize =
3088 framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1;
3090 // Create a frame at exatly that size.
3091 string big_value(kBigValueSize, 'x');
3092 syn_stream.SetHeader("aa", big_value.c_str());
3093 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3094 // neither support that in Chromium, nor do we use the same DFATAL (see
3095 // SpdyFrameBuilder::WriteFramePrefix()).
3096 control_frame.reset(framer.SerializeSynStream(syn_stream));
3098 EXPECT_TRUE(control_frame.get() != NULL);
3099 EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1,
3100 control_frame->size());
3102 TestSpdyVisitor visitor(spdy_version_);
3103 visitor.SimulateInFramer(
3104 reinterpret_cast<unsigned char*>(control_frame->data()),
3105 control_frame->size());
3106 EXPECT_FALSE(visitor.header_buffer_valid_);
3107 EXPECT_EQ(1, visitor.error_count_);
3108 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3109 visitor.framer_.error_code())
3110 << SpdyFramer::ErrorCodeToString(framer.error_code());
3111 EXPECT_EQ(0, visitor.syn_frame_count_);
3112 EXPECT_EQ(0u, visitor.header_buffer_length_);
3115 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3116 if (spdy_version_ < SPDY4) {
3117 return;
3119 SpdyFramer framer(spdy_version_);
3120 framer.set_enable_compression(false);
3121 SpdyHeadersIR headers(1);
3123 // Exact payload length will change with HPACK, but this should be long
3124 // enough to cause an overflow.
3125 const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize();
3126 string big_value(kBigValueSize, 'x');
3127 headers.SetHeader("aa", big_value.c_str());
3128 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3129 EXPECT_TRUE(control_frame.get() != NULL);
3130 EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize());
3132 TestSpdyVisitor visitor(spdy_version_);
3133 visitor.SimulateInFramer(
3134 reinterpret_cast<unsigned char*>(control_frame->data()),
3135 control_frame->size());
3136 EXPECT_TRUE(visitor.header_buffer_valid_);
3137 EXPECT_EQ(0, visitor.error_count_);
3138 EXPECT_EQ(1, visitor.headers_frame_count_);
3139 EXPECT_EQ(1, visitor.continuation_count_);
3140 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3143 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3144 if (spdy_version_ < SPDY4) {
3145 return;
3147 SpdyFramer framer(spdy_version_);
3148 framer.set_enable_compression(false);
3149 SpdyPushPromiseIR push_promise(1, 2);
3151 // Exact payload length will change with HPACK, but this should be long
3152 // enough to cause an overflow.
3153 const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize();
3154 string big_value(kBigValueSize, 'x');
3155 push_promise.SetHeader("aa", big_value.c_str());
3156 scoped_ptr<SpdyFrame> control_frame(
3157 framer.SerializePushPromise(push_promise));
3158 EXPECT_TRUE(control_frame.get() != NULL);
3159 EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize());
3161 TestSpdyVisitor visitor(spdy_version_);
3162 visitor.SimulateInFramer(
3163 reinterpret_cast<unsigned char*>(control_frame->data()),
3164 control_frame->size());
3165 EXPECT_TRUE(visitor.header_buffer_valid_);
3166 EXPECT_EQ(0, visitor.error_count_);
3167 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3168 EXPECT_EQ(1, visitor.continuation_count_);
3169 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3172 // Check that the framer stops delivering header data chunks once the visitor
3173 // declares it doesn't want any more. This is important to guard against
3174 // "zip bomb" types of attacks.
3175 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3176 const size_t kHeaderBufferChunks = 4;
3177 const size_t kHeaderBufferSize =
3178 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3179 const size_t kBigValueSize = kHeaderBufferSize * 2;
3180 string big_value(kBigValueSize, 'x');
3181 SpdyFramer framer(spdy_version_);
3182 SpdySynStreamIR syn_stream(1);
3183 syn_stream.set_priority(1);
3184 syn_stream.set_fin(true);
3185 syn_stream.SetHeader("aa", big_value.c_str());
3186 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3187 EXPECT_TRUE(control_frame.get() != NULL);
3188 TestSpdyVisitor visitor(spdy_version_);
3189 visitor.set_header_buffer_size(kHeaderBufferSize);
3190 visitor.use_compression_ = true;
3191 visitor.SimulateInFramer(
3192 reinterpret_cast<unsigned char*>(control_frame->data()),
3193 control_frame->size());
3194 EXPECT_FALSE(visitor.header_buffer_valid_);
3195 EXPECT_EQ(1, visitor.error_count_);
3196 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3197 visitor.framer_.error_code())
3198 << SpdyFramer::ErrorCodeToString(framer.error_code());
3200 // The framer should have stoped delivering chunks after the visitor
3201 // signaled "stop" by returning false from OnControlFrameHeaderData().
3203 // control_frame_header_data_count_ depends on the random sequence
3204 // produced by rand(), so adding, removing or running single tests
3205 // alters this value. The best we can do is assert that it happens
3206 // at least kHeaderBufferChunks + 1.
3207 EXPECT_LE(kHeaderBufferChunks + 1,
3208 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3209 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3211 // The framer should not have sent half-close to the visitor.
3212 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3215 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3216 if (spdy_version_ > SPDY3) {
3217 // Deflate compression doesn't apply to HPACK.
3218 return;
3220 SpdyFramer framer(spdy_version_);
3221 framer.set_enable_compression(false);
3222 // Construct a SYN_STREAM control frame without compressing the header block,
3223 // and have the framer try to decompress it. This will cause the framer to
3224 // deal with a decompression error.
3225 SpdySynStreamIR syn_stream(1);
3226 syn_stream.set_priority(1);
3227 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3228 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3229 TestSpdyVisitor visitor(spdy_version_);
3230 visitor.use_compression_ = true;
3231 visitor.SimulateInFramer(
3232 reinterpret_cast<unsigned char*>(control_frame->data()),
3233 control_frame->size());
3234 EXPECT_EQ(1, visitor.error_count_);
3235 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3236 << SpdyFramer::ErrorCodeToString(framer.error_code());
3237 EXPECT_EQ(0u, visitor.header_buffer_length_);
3240 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3241 SpdyFramer framer(spdy_version_);
3242 // Create a GoAway frame that has a few extra bytes at the end.
3243 // We create enough overhead to overflow the framer's control frame buffer.
3244 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize);
3245 const unsigned char length = 1 + SpdyFramer::kControlFrameBufferSize;
3246 const unsigned char kV3FrameData[] = { // Also applies for V2.
3247 0x80, spdy_version_ch_, 0x00, 0x07,
3248 0x00, 0x00, 0x00, length,
3249 0x00, 0x00, 0x00, 0x00, // Stream ID
3250 0x00, 0x00, 0x00, 0x00, // Status
3253 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3254 // since it may carry opaque data. Verify that minimal length is tested.
3255 const unsigned char less_than_min_length =
3256 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3257 const unsigned char kV4FrameData[] = {
3258 0x00, static_cast<uint8>(less_than_min_length), 0x07, 0x00,
3259 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, // Stream Id
3261 0x00, 0x00, 0x00, 0x00, // Status
3263 const size_t pad_length =
3264 length + framer.GetControlFrameHeaderSize() -
3265 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3266 string pad('A', pad_length);
3267 TestSpdyVisitor visitor(spdy_version_);
3269 if (IsSpdy4()) {
3270 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3271 } else {
3272 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3274 visitor.SimulateInFramer(
3275 reinterpret_cast<const unsigned char*>(pad.c_str()),
3276 pad.length());
3278 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3279 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3280 visitor.framer_.error_code())
3281 << SpdyFramer::ErrorCodeToString(framer.error_code());
3282 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3285 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3286 SpdyFramer framer(spdy_version_);
3287 SpdySettingsIR settings_ir;
3288 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3289 SetFrameLength(control_frame.get(), 0, spdy_version_);
3290 TestSpdyVisitor visitor(spdy_version_);
3291 visitor.use_compression_ = false;
3292 visitor.SimulateInFramer(
3293 reinterpret_cast<unsigned char*>(control_frame->data()),
3294 framer.GetControlFrameHeaderSize());
3295 if (spdy_version_ <= SPDY3) {
3296 // Should generate an error, since zero-len settings frames are unsupported.
3297 EXPECT_EQ(1, visitor.error_count_);
3298 } else {
3299 // Zero-len settings frames are permitted as of SPDY 4.
3300 EXPECT_EQ(0, visitor.error_count_);
3304 // Tests handling of SETTINGS frames with invalid length.
3305 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3306 SpdyFramer framer(spdy_version_);
3307 SpdySettingsIR settings_ir;
3309 // Add a setting to pad the frame so that we don't get a buffer overflow when
3310 // calling SimulateInFramer() below.
3311 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3312 false,
3313 false,
3314 0x00000002);
3315 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3316 const size_t kNewLength = 14;
3317 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3318 TestSpdyVisitor visitor(spdy_version_);
3319 visitor.use_compression_ = false;
3320 visitor.SimulateInFramer(
3321 reinterpret_cast<unsigned char*>(control_frame->data()),
3322 framer.GetControlFrameHeaderSize() + kNewLength);
3323 // Should generate an error, since its not possible to have a
3324 // settings frame of length kNewLength.
3325 EXPECT_EQ(1, visitor.error_count_);
3328 // Tests handling of SETTINGS frames larger than the frame buffer size.
3329 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3330 SpdyFramer framer(spdy_version_);
3331 SpdySettingsIR settings_ir;
3332 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3333 false, // persist
3334 false, // persisted
3336 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3337 false, // persist
3338 false, // persisted
3340 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3341 false, // persist
3342 false, // persisted
3345 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3346 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3347 control_frame->size());
3348 TestSpdyVisitor visitor(spdy_version_);
3349 visitor.use_compression_ = false;
3351 // Read all at once.
3352 visitor.SimulateInFramer(
3353 reinterpret_cast<unsigned char*>(control_frame->data()),
3354 control_frame->size());
3355 EXPECT_EQ(0, visitor.error_count_);
3356 EXPECT_EQ(3, visitor.setting_count_);
3357 if (spdy_version_ > SPDY3) {
3358 EXPECT_EQ(1, visitor.settings_ack_sent_);
3361 // Read data in small chunks.
3362 size_t framed_data = 0;
3363 size_t unframed_data = control_frame->size();
3364 size_t kReadChunkSize = 5; // Read five bytes at a time.
3365 while (unframed_data > 0) {
3366 size_t to_read = min(kReadChunkSize, unframed_data);
3367 visitor.SimulateInFramer(
3368 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3369 to_read);
3370 unframed_data -= to_read;
3371 framed_data += to_read;
3373 EXPECT_EQ(0, visitor.error_count_);
3374 EXPECT_EQ(3 * 2, visitor.setting_count_);
3375 if (spdy_version_ > SPDY3) {
3376 EXPECT_EQ(2, visitor.settings_ack_sent_);
3380 // Tests handling of SETTINGS frame with duplicate entries.
3381 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3382 SpdyFramer framer(spdy_version_);
3384 const unsigned char kV2FrameData[] = {
3385 0x80, spdy_version_ch_, 0x00, 0x04,
3386 0x00, 0x00, 0x00, 0x1C,
3387 0x00, 0x00, 0x00, 0x03,
3388 0x01, 0x00, 0x00, 0x00, // 1st Setting
3389 0x00, 0x00, 0x00, 0x02,
3390 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3391 0x00, 0x00, 0x00, 0x03,
3392 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3393 0x00, 0x00, 0x00, 0x03,
3395 const unsigned char kV3FrameData[] = {
3396 0x80, spdy_version_ch_, 0x00, 0x04,
3397 0x00, 0x00, 0x00, 0x1C,
3398 0x00, 0x00, 0x00, 0x03,
3399 0x00, 0x00, 0x00, 0x01, // 1st Setting
3400 0x00, 0x00, 0x00, 0x02,
3401 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3402 0x00, 0x00, 0x00, 0x03,
3403 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3404 0x00, 0x00, 0x00, 0x03,
3406 const unsigned char kV4FrameData[] = {
3407 0x00, 0x0f, 0x04, 0x00,
3408 0x00, 0x00, 0x00, 0x00,
3409 0x01, // 1st Setting
3410 0x00, 0x00, 0x00, 0x02,
3411 0x01, // 2nd (duplicate) Setting
3412 0x00, 0x00, 0x00, 0x03,
3413 0x03, // 3rd (unprocessed) Setting
3414 0x00, 0x00, 0x00, 0x03,
3417 TestSpdyVisitor visitor(spdy_version_);
3418 visitor.use_compression_ = false;
3419 if (IsSpdy2()) {
3420 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3421 } else if (IsSpdy3()) {
3422 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3423 } else {
3424 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3427 if (!IsSpdy4()) {
3428 EXPECT_EQ(1, visitor.setting_count_);
3429 EXPECT_EQ(1, visitor.error_count_);
3430 } else {
3431 // In SPDY 4+, duplicate settings are allowed;
3432 // each setting replaces the previous value for that setting.
3433 EXPECT_EQ(3, visitor.setting_count_);
3434 EXPECT_EQ(0, visitor.error_count_);
3435 EXPECT_EQ(1, visitor.settings_ack_sent_);
3439 // Tests handling of SETTINGS frame with entries out of order.
3440 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
3441 SpdyFramer framer(spdy_version_);
3443 const unsigned char kV2FrameData[] = {
3444 0x80, spdy_version_ch_, 0x00, 0x04,
3445 0x00, 0x00, 0x00, 0x1C,
3446 0x00, 0x00, 0x00, 0x03,
3447 0x02, 0x00, 0x00, 0x00, // 1st Setting
3448 0x00, 0x00, 0x00, 0x02,
3449 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
3450 0x00, 0x00, 0x00, 0x03,
3451 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3452 0x00, 0x00, 0x00, 0x03,
3454 const unsigned char kV3FrameData[] = {
3455 0x80, spdy_version_ch_, 0x00, 0x04,
3456 0x00, 0x00, 0x00, 0x1C,
3457 0x00, 0x00, 0x00, 0x03,
3458 0x00, 0x00, 0x00, 0x02, // 1st Setting
3459 0x00, 0x00, 0x00, 0x02,
3460 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3461 0x00, 0x00, 0x00, 0x03,
3462 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3463 0x00, 0x00, 0x00, 0x03,
3465 const unsigned char kV4FrameData[] = {
3466 0x00, 0x0f, 0x04, 0x00,
3467 0x00, 0x00, 0x00, 0x00,
3468 0x02, // 1st Setting
3469 0x00, 0x00, 0x00, 0x02,
3470 0x01, // 2nd (out of order) Setting
3471 0x00, 0x00, 0x00, 0x03,
3472 0x03, // 3rd (unprocessed) Setting
3473 0x00, 0x00, 0x00, 0x03,
3476 TestSpdyVisitor visitor(spdy_version_);
3477 visitor.use_compression_ = false;
3478 if (IsSpdy2()) {
3479 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3480 } else if (IsSpdy3()) {
3481 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3482 } else {
3483 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3486 if (!IsSpdy4()) {
3487 EXPECT_EQ(1, visitor.setting_count_);
3488 EXPECT_EQ(1, visitor.error_count_);
3489 } else {
3490 // In SPDY 4+, settings are allowed in any order.
3491 EXPECT_EQ(3, visitor.setting_count_);
3492 EXPECT_EQ(0, visitor.error_count_);
3493 // EXPECT_EQ(1, visitor.settings_ack_count_);
3497 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
3498 if (spdy_version_ <= SPDY3) {
3499 return;
3501 SpdyFramer framer(spdy_version_);
3503 const unsigned char kFrameData[] = {
3504 0x00, 0x00, 0x04, 0x01,
3505 0x00, 0x00, 0x00, 0x00,
3508 TestSpdyVisitor visitor(spdy_version_);
3509 visitor.use_compression_ = false;
3510 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
3512 EXPECT_EQ(0, visitor.error_count_);
3513 EXPECT_EQ(0, visitor.setting_count_);
3514 EXPECT_EQ(1, visitor.settings_ack_received_);
3518 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
3519 if (spdy_version_ <= SPDY3) {
3520 return;
3523 const int kPaddingLen = 512; // So we get two bytes for padding length field.
3524 const char data_payload[] = "hello";
3526 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3527 SpdyFramer framer(spdy_version_);
3528 framer.set_visitor(&visitor);
3530 SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
3531 data_ir.set_padding_len(kPaddingLen);
3532 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
3533 ASSERT_TRUE(frame.get() != NULL);
3535 int bytes_consumed = 0;
3537 // Send the frame header.
3538 EXPECT_CALL(visitor, OnDataFrameHeader(1,
3539 kPaddingLen + strlen(data_payload),
3540 false));
3541 CHECK_EQ(8u, framer.ProcessInput(frame->data(), 8));
3542 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH);
3543 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3544 bytes_consumed += 8;
3546 // Send the first byte of the padding length field.
3547 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
3548 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH);
3549 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3550 bytes_consumed += 1;
3552 // Send the second byte of the padding length field.
3553 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
3554 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3555 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3556 bytes_consumed += 1;
3558 // Send the first two bytes of the data payload.
3559 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
3560 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
3561 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3562 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3563 bytes_consumed += 2;
3565 // Send the rest three bytes of the data payload.
3566 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
3567 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
3568 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3569 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3570 bytes_consumed += 3;
3572 // Send the first 100 bytes of the padding payload.
3573 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false));
3574 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
3575 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3576 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3577 bytes_consumed += 100;
3579 // Send rest of the padding payload.
3580 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 410, false));
3581 CHECK_EQ(410u, framer.ProcessInput(frame->data() + bytes_consumed, 410));
3582 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
3583 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3586 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
3587 SpdyFramer framer(spdy_version_);
3588 scoped_ptr<SpdyFrame> control_frame(
3589 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3590 TestSpdyVisitor visitor(spdy_version_);
3591 visitor.SimulateInFramer(
3592 reinterpret_cast<unsigned char*>(control_frame->data()),
3593 control_frame->size());
3594 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3595 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3598 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
3599 if (!IsSpdy3()) {
3600 return;
3602 SpdyFramer framer(spdy_version_);
3603 const unsigned char kV3FrameData[] = { // Also applies for V2.
3604 0x80, spdy_version_ch_, 0x00, 0x0A,
3605 0x00, 0x00, 0x00, 0x33,
3606 0x00, 0x03, 0x00, 0x00,
3607 0x00, 0x05, 'p', 'r',
3608 'o', 'o', 'f', 0x00,
3609 0x00, 0x00, 0x06, 'a',
3610 ' ', 'c', 'e', 'r',
3611 't', 0x00, 0x00, 0x00,
3612 0x0C, 'a', 'n', 'o',
3613 't', 'h', 'e', 'r',
3614 ' ', 'c', 'e', 'r',
3615 't', 0x00, 0x00, 0x00,
3616 0x0A, 'f', 'i', 'n',
3617 'a', 'l', ' ', 'c',
3618 'e', 'r', 't',
3620 TestSpdyVisitor visitor(spdy_version_);
3621 visitor.use_compression_ = false;
3622 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
3623 EXPECT_EQ(0, visitor.error_count_);
3626 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
3627 if (!IsSpdy3()) {
3628 return;
3630 SpdyFramer framer(spdy_version_);
3631 const unsigned char kV3FrameData[] = { // Also applies for V2.
3632 0x80, spdy_version_ch_, 0x00, 0x0A,
3633 0x00, 0x00, 0x00, 0x33,
3634 0x00, 0x03, 0x00, 0x00,
3635 0x00, 0x05, 'p', 'r',
3636 'o', 'o', 'f', 0x00,
3637 0x00, 0x00, 0x06, 'a',
3638 ' ', 'c', 'e', 'r',
3639 't', 0x00, 0x00, 0x00,
3640 0x0C, 'a', 'n', 'o',
3641 't', 'h', 'e', 'r',
3642 ' ', 'c', 'e', 'r',
3643 't', 0x00, 0x00, 0x00,
3644 0x0A, 'f', 'i', 'n',
3645 'a', 'l', ' ', 'c',
3646 'e', 'r', 't',
3648 TestSpdyVisitor visitor(spdy_version_);
3649 visitor.use_compression_ = false;
3650 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
3651 arraysize(kV3FrameData));
3652 scoped_ptr<SpdyFrame> control_frame(
3653 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3654 multiple_frame_data.append(string(control_frame->data(),
3655 control_frame->size()));
3656 visitor.SimulateInFramer(
3657 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
3658 multiple_frame_data.length());
3659 EXPECT_EQ(0, visitor.error_count_);
3660 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3661 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3664 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3665 if (spdy_version_ < SPDY4) {
3666 return;
3669 SpdyFramer framer(spdy_version_);
3670 framer.set_enable_compression(false);
3671 const char kDescription[] = "CONTINUATION frame";
3673 const unsigned char kFrameData[] = {
3674 0x00, 0x12, 0x09, 0x00, // CONTINUATION
3675 0x00, 0x00, 0x00, 0x2a, // Stream 42
3676 0x40, 0x03, 0x62, 0x61, // @.ba
3677 0x72, 0x03, 0x66, 0x6f, // r.fo
3678 0x6f, 0x40, 0x03, 0x66, // o@.f
3679 0x6f, 0x6f, 0x03, 0x62, // oo.b
3680 0x61, 0x72, // ar
3683 SpdyContinuationIR continuation(42);
3684 continuation.SetHeader("bar", "foo");
3685 continuation.SetHeader("foo", "bar");
3686 scoped_ptr<SpdySerializedFrame> frame(
3687 framer.SerializeContinuation(continuation));
3688 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3691 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
3692 if (spdy_version_ <= SPDY3) {
3693 return;
3696 SpdyFramer framer(spdy_version_);
3697 SpdyPushPromiseIR push_promise(42, 57);
3698 push_promise.SetHeader("foo", "bar");
3699 push_promise.SetHeader("bar", "foofoo");
3700 SpdyHeaderBlock headers = push_promise.name_value_block();
3701 scoped_ptr<SpdySerializedFrame> frame(
3702 framer.SerializePushPromise(push_promise));
3703 EXPECT_TRUE(frame.get() != NULL);
3704 TestSpdyVisitor visitor(spdy_version_);
3705 visitor.use_compression_ = true;
3706 visitor.SimulateInFramer(
3707 reinterpret_cast<unsigned char*>(frame->data()),
3708 frame->size());
3709 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
3710 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
3711 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3714 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
3715 if (spdy_version_ <= SPDY3) {
3716 return;
3719 const unsigned char kInput[] = {
3720 0x00, 0x10, 0x01, 0x00, // HEADERS
3721 0x00, 0x00, 0x00, 0x01, // Stream 1
3722 0x40, 0x06, 0x43, 0x6f,
3723 0x6f, 0x6b, 0x69, 0x65,
3724 0x07, 0x66, 0x6f, 0x6f,
3725 0x3d, 0x62, 0x61, 0x72,
3727 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3728 0x00, 0x00, 0x00, 0x01, // Stream 1
3729 0x40, 0x06, 0x43, 0x6f,
3730 0x6f, 0x6b, 0x69, 0x65,
3731 0x08, 0x62, 0x61, 0x7a,
3732 0x3d, 0x62, 0x69, 0x6e,
3733 0x67, 0x40, 0x06, 0x43,
3735 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3736 0x00, 0x00, 0x00, 0x01, // Stream 1
3737 0x6f, 0x6f, 0x6b, 0x69,
3738 0x65, 0x00, 0x40, 0x04,
3739 0x6e, 0x61, 0x6d, 0x65,
3740 0x05, 0x76, 0x61, 0x6c,
3741 0x75, 0x65,
3744 SpdyFramer framer(spdy_version_);
3745 TestSpdyVisitor visitor(spdy_version_);
3746 visitor.SimulateInFramer(kInput, sizeof(kInput));
3748 EXPECT_EQ(0, visitor.error_count_);
3749 EXPECT_EQ(1, visitor.headers_frame_count_);
3750 EXPECT_EQ(2, visitor.continuation_count_);
3751 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3752 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3754 EXPECT_THAT(visitor.headers_, ElementsAre(
3755 Pair("Cookie", "foo=bar; baz=bing; "),
3756 Pair("name", "value")));
3759 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
3760 if (spdy_version_ <= SPDY3) {
3761 return;
3764 const unsigned char kInput[] = {
3765 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
3766 0x00, 0x00, 0x00, 0x01, // Stream 1
3767 0x40, 0x06, 0x43, 0x6f,
3768 0x6f, 0x6b, 0x69, 0x65,
3769 0x07, 0x66, 0x6f, 0x6f,
3770 0x3d, 0x62, 0x61, 0x72,
3772 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3773 0x00, 0x00, 0x00, 0x01, // Stream 1
3774 0x40, 0x06, 0x43, 0x6f,
3775 0x6f, 0x6b, 0x69, 0x65,
3776 0x08, 0x62, 0x61, 0x7a,
3777 0x3d, 0x62, 0x69, 0x6e,
3778 0x67, 0x40, 0x06, 0x43,
3780 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3781 0x00, 0x00, 0x00, 0x01, // Stream 1
3782 0x6f, 0x6f, 0x6b, 0x69,
3783 0x65, 0x00, 0x40, 0x04,
3784 0x6e, 0x61, 0x6d, 0x65,
3785 0x05, 0x76, 0x61, 0x6c,
3786 0x75, 0x65,
3789 SpdyFramer framer(spdy_version_);
3790 TestSpdyVisitor visitor(spdy_version_);
3791 visitor.SimulateInFramer(kInput, sizeof(kInput));
3793 EXPECT_EQ(0, visitor.error_count_);
3794 EXPECT_EQ(1, visitor.headers_frame_count_);
3795 EXPECT_EQ(2, visitor.continuation_count_);
3796 EXPECT_EQ(1, visitor.fin_flag_count_);
3797 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3798 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3800 EXPECT_THAT(visitor.headers_, ElementsAre(
3801 Pair("Cookie", "foo=bar; baz=bing; "),
3802 Pair("name", "value")));
3805 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
3806 if (spdy_version_ <= SPDY3) {
3807 return;
3810 const unsigned char kInput[] = {
3811 0x00, 0x14, 0x05, 0x00, // PUSH_PROMISE
3812 0x00, 0x00, 0x00, 0x01, // Stream 1
3813 0x00, 0x00, 0x00, 0x2A, // Promised stream 42
3814 0x40, 0x06, 0x43, 0x6f,
3815 0x6f, 0x6b, 0x69, 0x65,
3816 0x07, 0x66, 0x6f, 0x6f,
3817 0x3d, 0x62, 0x61, 0x72,
3819 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3820 0x00, 0x00, 0x00, 0x01, // Stream 1
3821 0x40, 0x06, 0x43, 0x6f,
3822 0x6f, 0x6b, 0x69, 0x65,
3823 0x08, 0x62, 0x61, 0x7a,
3824 0x3d, 0x62, 0x69, 0x6e,
3825 0x67, 0x40, 0x06, 0x43,
3827 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3828 0x00, 0x00, 0x00, 0x01, // Stream 1
3829 0x6f, 0x6f, 0x6b, 0x69,
3830 0x65, 0x00, 0x40, 0x04,
3831 0x6e, 0x61, 0x6d, 0x65,
3832 0x05, 0x76, 0x61, 0x6c,
3833 0x75, 0x65,
3836 SpdyFramer framer(spdy_version_);
3837 TestSpdyVisitor visitor(spdy_version_);
3838 visitor.SimulateInFramer(kInput, sizeof(kInput));
3840 EXPECT_EQ(0, visitor.error_count_);
3841 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
3842 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
3843 EXPECT_EQ(2, visitor.continuation_count_);
3844 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3845 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3847 EXPECT_THAT(visitor.headers_, ElementsAre(
3848 Pair("Cookie", "foo=bar; baz=bing; "),
3849 Pair("name", "value")));
3852 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
3853 if (spdy_version_ <= SPDY3) {
3854 return;
3857 const unsigned char kInput[] = {
3858 0x00, 0x10, 0x01, 0x00, // HEADERS
3859 0x00, 0x00, 0x00, 0x01, // Stream 1
3860 0x40, 0x06, 0x43, 0x6f,
3861 0x6f, 0x6b, 0x69, 0x65,
3862 0x07, 0x66, 0x6f, 0x6f,
3863 0x3d, 0x62, 0x61, 0x72,
3865 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3866 0x00, 0x00, 0x00, 0x02, // Stream 2
3867 0x40, 0x06, 0x43, 0x6f,
3868 0x6f, 0x6b, 0x69, 0x65,
3869 0x08, 0x62, 0x61, 0x7a,
3870 0x3d, 0x62, 0x69, 0x6e,
3871 0x67, 0x40, 0x06, 0x43,
3874 SpdyFramer framer(spdy_version_);
3875 TestSpdyVisitor visitor(spdy_version_);
3876 framer.set_visitor(&visitor);
3877 visitor.SimulateInFramer(kInput, sizeof(kInput));
3879 EXPECT_EQ(1, visitor.error_count_);
3880 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3881 visitor.framer_.error_code())
3882 << SpdyFramer::ErrorCodeToString(framer.error_code());
3883 EXPECT_EQ(1, visitor.headers_frame_count_);
3884 EXPECT_EQ(0, visitor.continuation_count_);
3885 EXPECT_EQ(0u, visitor.header_buffer_length_);
3888 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
3889 if (spdy_version_ <= SPDY3) {
3890 return;
3893 const unsigned char kInput[] = {
3894 0x00, 0x10, 0x09, 0x00, // CONTINUATION
3895 0x00, 0x00, 0x00, 0x01, // Stream 1
3896 0x40, 0x06, 0x43, 0x6f,
3897 0x6f, 0x6b, 0x69, 0x65,
3898 0x07, 0x66, 0x6f, 0x6f,
3899 0x3d, 0x62, 0x61, 0x72,
3902 SpdyFramer framer(spdy_version_);
3903 TestSpdyVisitor visitor(spdy_version_);
3904 framer.set_visitor(&visitor);
3905 visitor.SimulateInFramer(kInput, sizeof(kInput));
3907 EXPECT_EQ(1, visitor.error_count_);
3908 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3909 visitor.framer_.error_code())
3910 << SpdyFramer::ErrorCodeToString(framer.error_code());
3911 EXPECT_EQ(0, visitor.continuation_count_);
3912 EXPECT_EQ(0u, visitor.header_buffer_length_);
3915 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
3916 if (spdy_version_ <= SPDY3) {
3917 return;
3920 const unsigned char kInput[] = {
3921 0x00, 0x10, 0x01, 0x00, // HEADERS
3922 0x00, 0x00, 0x00, 0x01, // Stream 1
3923 0x40, 0x06, 0x43, 0x6f,
3924 0x6f, 0x6b, 0x69, 0x65,
3925 0x07, 0x66, 0x6f, 0x6f,
3926 0x3d, 0x62, 0x61, 0x72,
3928 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
3929 0x00, 0x00, 0x00, 0x04,
3930 0xde, 0xad, 0xbe, 0xef,
3933 SpdyFramer framer(spdy_version_);
3934 TestSpdyVisitor visitor(spdy_version_);
3935 framer.set_visitor(&visitor);
3936 visitor.SimulateInFramer(kInput, sizeof(kInput));
3938 EXPECT_EQ(1, visitor.error_count_);
3939 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3940 visitor.framer_.error_code())
3941 << SpdyFramer::ErrorCodeToString(framer.error_code());
3942 EXPECT_EQ(1, visitor.headers_frame_count_);
3943 EXPECT_EQ(0, visitor.continuation_count_);
3944 EXPECT_EQ(0u, visitor.header_buffer_length_);
3945 EXPECT_EQ(0, visitor.data_frame_count_);
3948 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
3949 if (spdy_version_ <= SPDY3) {
3950 return;
3953 const unsigned char kInput[] = {
3954 0x00, 0x10, 0x01, 0x00, // HEADERS
3955 0x00, 0x00, 0x00, 0x01, // Stream 1
3956 0x40, 0x06, 0x43, 0x6f,
3957 0x6f, 0x6b, 0x69, 0x65,
3958 0x07, 0x66, 0x6f, 0x6f,
3959 0x3d, 0x62, 0x61, 0x72,
3961 0x00, 0x14, 0x08, 0x00, // HEADERS
3962 0x00, 0x00, 0x00, 0x01, // Stream 1
3963 0x40, 0x06, 0x43, 0x6f, // (Note this is a valid continued encoding).
3964 0x6f, 0x6b, 0x69, 0x65,
3965 0x08, 0x62, 0x61, 0x7a,
3966 0x3d, 0x62, 0x69, 0x6e,
3967 0x67, 0x40, 0x06, 0x43,
3970 SpdyFramer framer(spdy_version_);
3971 TestSpdyVisitor visitor(spdy_version_);
3972 framer.set_visitor(&visitor);
3973 visitor.SimulateInFramer(kInput, sizeof(kInput));
3975 EXPECT_EQ(1, visitor.error_count_);
3976 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3977 visitor.framer_.error_code())
3978 << SpdyFramer::ErrorCodeToString(framer.error_code());
3979 EXPECT_EQ(1, visitor.headers_frame_count_);
3980 EXPECT_EQ(0, visitor.continuation_count_);
3981 EXPECT_EQ(0u, visitor.header_buffer_length_);
3982 EXPECT_EQ(0, visitor.data_frame_count_);
3985 TEST_P(SpdyFramerTest, ReadGarbage) {
3986 SpdyFramer framer(spdy_version_);
3987 unsigned char garbage_frame[256];
3988 memset(garbage_frame, ~0, sizeof(garbage_frame));
3989 TestSpdyVisitor visitor(spdy_version_);
3990 visitor.use_compression_ = false;
3991 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
3992 EXPECT_EQ(1, visitor.error_count_);
3995 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
3996 if (!IsSpdy4()) {
3997 return;
3999 SpdyFramer framer(spdy_version_);
4000 const unsigned char kFrameData[] = {
4001 0x00, 0x10, 0xff, 0xff,
4002 0xff, 0xff, 0xff, 0xff,
4003 0xff, 0xff, 0xff, 0xff,
4004 0xff, 0xff, 0xff, 0xff,
4006 TestSpdyVisitor visitor(spdy_version_);
4007 visitor.use_compression_ = false;
4008 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4009 EXPECT_EQ(1, visitor.error_count_);
4012 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4013 if (IsSpdy4()) {
4014 // Not valid for SPDY 4 since there is no version field.
4015 return;
4017 SpdyFramer framer(spdy_version_);
4018 const unsigned char kFrameData[] = {
4019 0x80, spdy_version_ch_, 0xff, 0xff,
4020 0xff, 0xff, 0xff, 0xff,
4022 TestSpdyVisitor visitor(spdy_version_);
4023 visitor.use_compression_ = false;
4024 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4025 EXPECT_EQ(1, visitor.error_count_);
4028 TEST_P(SpdyFramerTest, SizesTest) {
4029 SpdyFramer framer(spdy_version_);
4030 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4031 if (IsSpdy4()) {
4032 EXPECT_EQ(8u, framer.GetSynReplyMinimumSize());
4033 EXPECT_EQ(12u, framer.GetRstStreamMinimumSize());
4034 EXPECT_EQ(8u, framer.GetSettingsMinimumSize());
4035 EXPECT_EQ(16u, framer.GetPingSize());
4036 EXPECT_EQ(16u, framer.GetGoAwayMinimumSize());
4037 EXPECT_EQ(8u, framer.GetHeadersMinimumSize());
4038 EXPECT_EQ(12u, framer.GetWindowUpdateSize());
4039 EXPECT_EQ(8u, framer.GetBlockedSize());
4040 EXPECT_EQ(12u, framer.GetPushPromiseMinimumSize());
4041 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4042 EXPECT_EQ(16383u, framer.GetFrameMaximumSize());
4043 EXPECT_EQ(16375u, framer.GetDataFrameMaximumPayload());
4044 } else {
4045 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4046 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4047 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4048 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4049 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4050 EXPECT_EQ(12u, framer.GetPingSize());
4051 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4052 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4053 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4054 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4055 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4056 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4060 TEST_P(SpdyFramerTest, StateToStringTest) {
4061 EXPECT_STREQ("ERROR",
4062 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4063 EXPECT_STREQ("AUTO_RESET",
4064 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4065 EXPECT_STREQ("RESET",
4066 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4067 EXPECT_STREQ("READING_COMMON_HEADER",
4068 SpdyFramer::StateToString(
4069 SpdyFramer::SPDY_READING_COMMON_HEADER));
4070 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4071 SpdyFramer::StateToString(
4072 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4073 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4074 SpdyFramer::StateToString(
4075 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4076 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4077 SpdyFramer::StateToString(
4078 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4079 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4080 SpdyFramer::StateToString(
4081 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4082 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4083 SpdyFramer::StateToString(
4084 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4085 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4086 SpdyFramer::StateToString(
4087 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4088 EXPECT_STREQ("UNKNOWN_STATE",
4089 SpdyFramer::StateToString(
4090 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1));
4093 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4094 EXPECT_STREQ("NO_ERROR",
4095 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4096 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4097 SpdyFramer::ErrorCodeToString(
4098 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4099 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4100 SpdyFramer::ErrorCodeToString(
4101 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4102 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4103 SpdyFramer::ErrorCodeToString(
4104 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4105 EXPECT_STREQ("UNSUPPORTED_VERSION",
4106 SpdyFramer::ErrorCodeToString(
4107 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4108 EXPECT_STREQ("DECOMPRESS_FAILURE",
4109 SpdyFramer::ErrorCodeToString(
4110 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4111 EXPECT_STREQ("COMPRESS_FAILURE",
4112 SpdyFramer::ErrorCodeToString(
4113 SpdyFramer::SPDY_COMPRESS_FAILURE));
4114 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4115 SpdyFramer::ErrorCodeToString(
4116 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4117 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4118 SpdyFramer::ErrorCodeToString(
4119 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4120 EXPECT_STREQ("UNKNOWN_ERROR",
4121 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4124 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4125 EXPECT_STREQ("INVALID",
4126 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4127 EXPECT_STREQ("PROTOCOL_ERROR",
4128 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4129 EXPECT_STREQ("INVALID_STREAM",
4130 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4131 EXPECT_STREQ("REFUSED_STREAM",
4132 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4133 EXPECT_STREQ("UNSUPPORTED_VERSION",
4134 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4135 EXPECT_STREQ("CANCEL",
4136 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4137 EXPECT_STREQ("INTERNAL_ERROR",
4138 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4139 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4140 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4141 EXPECT_STREQ("UNKNOWN_STATUS",
4142 SpdyFramer::StatusCodeToString(-1));
4145 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4146 EXPECT_STREQ("DATA",
4147 SpdyFramer::FrameTypeToString(DATA));
4148 EXPECT_STREQ("SYN_STREAM",
4149 SpdyFramer::FrameTypeToString(SYN_STREAM));
4150 EXPECT_STREQ("SYN_REPLY",
4151 SpdyFramer::FrameTypeToString(SYN_REPLY));
4152 EXPECT_STREQ("RST_STREAM",
4153 SpdyFramer::FrameTypeToString(RST_STREAM));
4154 EXPECT_STREQ("SETTINGS",
4155 SpdyFramer::FrameTypeToString(SETTINGS));
4156 EXPECT_STREQ("NOOP",
4157 SpdyFramer::FrameTypeToString(NOOP));
4158 EXPECT_STREQ("PING",
4159 SpdyFramer::FrameTypeToString(PING));
4160 EXPECT_STREQ("GOAWAY",
4161 SpdyFramer::FrameTypeToString(GOAWAY));
4162 EXPECT_STREQ("HEADERS",
4163 SpdyFramer::FrameTypeToString(HEADERS));
4164 EXPECT_STREQ("WINDOW_UPDATE",
4165 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4166 EXPECT_STREQ("PUSH_PROMISE",
4167 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4168 EXPECT_STREQ("CREDENTIAL",
4169 SpdyFramer::FrameTypeToString(CREDENTIAL));
4170 EXPECT_STREQ("CONTINUATION",
4171 SpdyFramer::FrameTypeToString(CONTINUATION));
4174 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4175 if (IsSpdy4()) {
4176 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4177 return;
4180 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4181 SpdyFramer framer(spdy_version_);
4182 framer.set_visitor(&visitor);
4184 EXPECT_CALL(visitor, OnError(_));
4185 framer.ProcessInput("HTTP/1.1", 8);
4186 EXPECT_TRUE(framer.probable_http_response());
4187 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4188 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4189 << SpdyFramer::ErrorCodeToString(framer.error_code());
4192 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4193 SpdyFramer framer(spdy_version_);
4194 framer.set_visitor(&visitor);
4196 EXPECT_CALL(visitor, OnError(_));
4197 framer.ProcessInput("HTTP/1.0", 8);
4198 EXPECT_TRUE(framer.probable_http_response());
4199 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4200 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4201 << SpdyFramer::ErrorCodeToString(framer.error_code());
4205 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4206 if (spdy_version_ > SPDY3) {
4207 return;
4210 for (int flags = 0; flags < 256; ++flags) {
4211 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4213 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4214 SpdyFramer framer(spdy_version_);
4215 framer.set_visitor(&visitor);
4217 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4218 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4219 SetFrameFlags(frame.get(), flags, spdy_version_);
4221 if (flags & ~DATA_FLAG_FIN) {
4222 EXPECT_CALL(visitor, OnError(_));
4223 } else {
4224 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4225 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4226 if (flags & DATA_FLAG_FIN) {
4227 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4231 framer.ProcessInput(frame->data(), frame->size());
4232 if (flags & ~DATA_FLAG_FIN) {
4233 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4234 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4235 framer.error_code())
4236 << SpdyFramer::ErrorCodeToString(framer.error_code());
4237 } else {
4238 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4239 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4240 << SpdyFramer::ErrorCodeToString(framer.error_code());
4245 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4246 if (spdy_version_ <= SPDY3) {
4247 return;
4250 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4251 DATA_FLAG_PAD_LOW | DATA_FLAG_PAD_HIGH;
4253 for (int flags = 0; flags < 256; ++flags) {
4254 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4256 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4257 SpdyFramer framer(spdy_version_);
4258 framer.set_visitor(&visitor);
4260 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4261 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4262 SetFrameFlags(frame.get(), flags, spdy_version_);
4264 if (flags & ~valid_data_flags) {
4265 EXPECT_CALL(visitor, OnError(_));
4266 } else {
4267 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4268 if ((flags & DATA_FLAG_PAD_LOW) || (flags & DATA_FLAG_PAD_HIGH)) {
4269 // Expect Error since we don't set pad_high and pad_low in payload.
4270 EXPECT_CALL(visitor, OnError(_));
4271 } else {
4272 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4273 if (flags & DATA_FLAG_FIN) {
4274 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4279 framer.ProcessInput(frame->data(), frame->size());
4280 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PAD_LOW) ||
4281 (flags & DATA_FLAG_PAD_HIGH)) {
4282 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4283 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4284 framer.error_code())
4285 << SpdyFramer::ErrorCodeToString(framer.error_code());
4286 } else {
4287 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4288 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4289 << SpdyFramer::ErrorCodeToString(framer.error_code());
4294 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4295 for (int flags = 0; flags < 256; ++flags) {
4296 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4298 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4299 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4300 SpdyFramer framer(spdy_version_);
4301 framer.set_visitor(&visitor);
4302 framer.set_debug_visitor(&debug_visitor);
4304 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4306 SpdySynStreamIR syn_stream(8);
4307 syn_stream.set_associated_to_stream_id(3);
4308 syn_stream.set_priority(1);
4309 syn_stream.SetHeader("foo", "bar");
4310 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4311 int set_flags = flags;
4312 if (IsSpdy4()) {
4313 // PRIORITY required for SYN_STREAM simulation.
4314 set_flags |= HEADERS_FLAG_PRIORITY;
4316 SetFrameFlags(frame.get(), set_flags, spdy_version_);
4318 if (!IsSpdy4() &&
4319 flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4320 EXPECT_CALL(visitor, OnError(_));
4321 } else if (IsSpdy4() &&
4322 flags & ~(CONTROL_FLAG_FIN |
4323 HEADERS_FLAG_PRIORITY |
4324 HEADERS_FLAG_END_HEADERS)) {
4325 EXPECT_CALL(visitor, OnError(_));
4326 } else {
4327 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
4328 if (IsSpdy4()) {
4329 EXPECT_CALL(visitor, OnSynStream(8, 0, 1, flags & CONTROL_FLAG_FIN,
4330 false));
4331 } else {
4332 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
4333 flags & CONTROL_FLAG_UNIDIRECTIONAL));
4335 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
4336 .WillRepeatedly(testing::Return(true));
4337 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
4338 flags & HEADERS_FLAG_END_HEADERS)) {
4339 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4340 } else {
4341 // Do not close the stream if we are expecting a CONTINUATION frame.
4342 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4346 framer.ProcessInput(frame->data(), frame->size());
4347 if (!IsSpdy4() &&
4348 flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4349 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4350 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4351 framer.error_code())
4352 << SpdyFramer::ErrorCodeToString(framer.error_code());
4353 } else if (IsSpdy4() &&
4354 flags & ~(CONTROL_FLAG_FIN |
4355 HEADERS_FLAG_PRIORITY |
4356 HEADERS_FLAG_END_HEADERS)) {
4357 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4358 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4359 framer.error_code())
4360 << SpdyFramer::ErrorCodeToString(framer.error_code());
4361 } else {
4362 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4363 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4364 << SpdyFramer::ErrorCodeToString(framer.error_code());
4369 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
4370 if (IsSpdy4()) {
4371 // Covered by HEADERS case.
4372 return;
4374 for (int flags = 0; flags < 256; ++flags) {
4375 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4377 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4378 SpdyFramer framer(spdy_version_);
4379 framer.set_visitor(&visitor);
4381 SpdySynReplyIR syn_reply(37);
4382 syn_reply.SetHeader("foo", "bar");
4383 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
4384 SetFrameFlags(frame.get(), flags, spdy_version_);
4386 if (flags & ~CONTROL_FLAG_FIN) {
4387 EXPECT_CALL(visitor, OnError(_));
4388 } else {
4389 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
4390 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
4391 .WillRepeatedly(testing::Return(true));
4392 if (flags & DATA_FLAG_FIN) {
4393 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4397 framer.ProcessInput(frame->data(), frame->size());
4398 if (flags & ~CONTROL_FLAG_FIN) {
4399 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4400 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4401 framer.error_code())
4402 << SpdyFramer::ErrorCodeToString(framer.error_code());
4403 } else {
4404 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4405 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4406 << SpdyFramer::ErrorCodeToString(framer.error_code());
4411 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
4412 for (int flags = 0; flags < 256; ++flags) {
4413 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4415 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4416 SpdyFramer framer(spdy_version_);
4417 framer.set_visitor(&visitor);
4419 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
4420 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
4421 SetFrameFlags(frame.get(), flags, spdy_version_);
4423 if (flags != 0) {
4424 EXPECT_CALL(visitor, OnError(_));
4425 } else {
4426 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
4429 framer.ProcessInput(frame->data(), frame->size());
4430 if (flags != 0) {
4431 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4432 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4433 framer.error_code())
4434 << SpdyFramer::ErrorCodeToString(framer.error_code());
4435 } else {
4436 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4437 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4438 << SpdyFramer::ErrorCodeToString(framer.error_code());
4443 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
4444 if (spdy_version_ > SPDY3) { return; }
4445 for (int flags = 0; flags < 256; ++flags) {
4446 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4448 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4449 SpdyFramer framer(spdy_version_);
4450 framer.set_visitor(&visitor);
4452 SpdySettingsIR settings_ir;
4453 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
4454 false,
4455 false,
4456 54321);
4457 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
4458 SetFrameFlags(frame.get(), flags, spdy_version_);
4460 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
4461 EXPECT_CALL(visitor, OnError(_));
4462 } else {
4463 EXPECT_CALL(visitor, OnSettings(
4464 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
4465 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
4466 SETTINGS_FLAG_NONE, 54321));
4467 EXPECT_CALL(visitor, OnSettingsEnd());
4470 framer.ProcessInput(frame->data(), frame->size());
4471 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
4472 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4473 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4474 framer.error_code())
4475 << SpdyFramer::ErrorCodeToString(framer.error_code());
4476 } else {
4477 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4478 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4479 << SpdyFramer::ErrorCodeToString(framer.error_code());
4484 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
4485 if (spdy_version_ <= SPDY3) { return; }
4486 for (int flags = 0; flags < 256; ++flags) {
4487 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4489 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4490 SpdyFramer framer(spdy_version_);
4491 framer.set_visitor(&visitor);
4493 SpdySettingsIR settings_ir;
4494 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
4495 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
4496 SetFrameFlags(frame.get(), flags, spdy_version_);
4498 if (flags != 0) {
4499 EXPECT_CALL(visitor, OnError(_));
4500 } else {
4501 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
4502 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
4503 EXPECT_CALL(visitor, OnSettingsEnd());
4506 framer.ProcessInput(frame->data(), frame->size());
4507 if (flags & ~SETTINGS_FLAG_ACK) {
4508 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4509 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4510 framer.error_code())
4511 << SpdyFramer::ErrorCodeToString(framer.error_code());
4512 } else if (flags & SETTINGS_FLAG_ACK) {
4513 // The frame is invalid because ACK frames should have no payload.
4514 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4515 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4516 framer.error_code())
4517 << SpdyFramer::ErrorCodeToString(framer.error_code());
4518 } else {
4519 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4520 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4521 << SpdyFramer::ErrorCodeToString(framer.error_code());
4526 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
4527 for (int flags = 0; flags < 256; ++flags) {
4528 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4530 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4531 SpdyFramer framer(spdy_version_);
4532 framer.set_visitor(&visitor);
4534 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
4535 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
4536 SetFrameFlags(frame.get(), flags, spdy_version_);
4538 if (flags != 0) {
4539 EXPECT_CALL(visitor, OnError(_));
4540 } else {
4541 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
4544 framer.ProcessInput(frame->data(), frame->size());
4545 if (flags != 0) {
4546 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4547 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4548 framer.error_code())
4549 << SpdyFramer::ErrorCodeToString(framer.error_code());
4550 } else {
4551 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4552 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4553 << SpdyFramer::ErrorCodeToString(framer.error_code());
4558 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
4559 for (int flags = 0; flags < 256; ++flags) {
4560 if (IsSpdy4() && flags & HEADERS_FLAG_PRIORITY) {
4561 // Covered by SYN_STREAM case.
4562 continue;
4564 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4566 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4567 SpdyFramer framer(spdy_version_);
4568 framer.set_visitor(&visitor);
4570 SpdyHeadersIR headers_ir(57);
4571 headers_ir.SetHeader("foo", "bar");
4572 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
4573 SetFrameFlags(frame.get(), flags, spdy_version_);
4575 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
4576 EXPECT_CALL(visitor, OnError(_));
4577 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
4578 HEADERS_FLAG_END_HEADERS)) {
4579 EXPECT_CALL(visitor, OnError(_));
4580 } else {
4581 EXPECT_CALL(visitor, OnHeaders(57,
4582 flags & CONTROL_FLAG_FIN,
4583 (flags & HEADERS_FLAG_END_HEADERS) ||
4584 !IsSpdy4()));
4585 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
4586 .WillRepeatedly(testing::Return(true));
4587 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
4588 flags & HEADERS_FLAG_END_HEADERS)) {
4589 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4590 } else {
4591 // Do not close the stream if we are expecting a CONTINUATION frame.
4592 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4596 framer.ProcessInput(frame->data(), frame->size());
4597 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
4598 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4599 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4600 framer.error_code())
4601 << SpdyFramer::ErrorCodeToString(framer.error_code());
4602 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
4603 HEADERS_FLAG_END_HEADERS)) {
4604 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4605 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4606 framer.error_code())
4607 << SpdyFramer::ErrorCodeToString(framer.error_code());
4608 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
4609 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4610 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4611 << SpdyFramer::ErrorCodeToString(framer.error_code());
4612 } else {
4613 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4614 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4615 << SpdyFramer::ErrorCodeToString(framer.error_code());
4620 TEST_P(SpdyFramerTest, PingFrameFlags) {
4621 for (int flags = 0; flags < 256; ++flags) {
4622 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4624 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4625 SpdyFramer framer(spdy_version_);
4626 framer.set_visitor(&visitor);
4628 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
4629 SetFrameFlags(frame.get(), flags, spdy_version_);
4631 if (spdy_version_ > SPDY3 &&
4632 flags == PING_FLAG_ACK) {
4633 EXPECT_CALL(visitor, OnPing(42, true));
4634 } else if (flags == 0) {
4635 EXPECT_CALL(visitor, OnPing(42, false));
4636 } else {
4637 EXPECT_CALL(visitor, OnError(_));
4640 framer.ProcessInput(frame->data(), frame->size());
4641 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
4642 flags == 0) {
4643 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4644 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4645 << SpdyFramer::ErrorCodeToString(framer.error_code());
4646 } else {
4647 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4648 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4649 framer.error_code())
4650 << SpdyFramer::ErrorCodeToString(framer.error_code());
4655 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
4656 for (int flags = 0; flags < 256; ++flags) {
4657 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4659 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4660 SpdyFramer framer(spdy_version_);
4661 framer.set_visitor(&visitor);
4663 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
4664 SpdyWindowUpdateIR(4, 1024)));
4665 SetFrameFlags(frame.get(), flags, spdy_version_);
4667 if (flags != 0) {
4668 EXPECT_CALL(visitor, OnError(_));
4669 } else {
4670 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
4673 framer.ProcessInput(frame->data(), frame->size());
4674 if (flags != 0) {
4675 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4676 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4677 framer.error_code())
4678 << SpdyFramer::ErrorCodeToString(framer.error_code());
4679 } else {
4680 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4681 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4682 << SpdyFramer::ErrorCodeToString(framer.error_code());
4687 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
4688 if (spdy_version_ < SPDY4) {
4689 return;
4692 for (int flags = 0; flags < 256; ++flags) {
4693 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4695 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
4696 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
4697 SpdyFramer framer(spdy_version_);
4698 framer.set_visitor(&visitor);
4699 framer.set_debug_visitor(&debug_visitor);
4701 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
4703 SpdyPushPromiseIR push_promise(42, 57);
4704 push_promise.SetHeader("foo", "bar");
4705 scoped_ptr<SpdySerializedFrame> frame(
4706 framer.SerializePushPromise(push_promise));
4707 SetFrameFlags(frame.get(), flags, spdy_version_);
4709 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
4710 EXPECT_CALL(visitor, OnError(_));
4711 } else {
4712 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
4713 EXPECT_CALL(visitor, OnPushPromise(42, 57,
4714 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
4715 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
4716 .WillRepeatedly(testing::Return(true));
4719 framer.ProcessInput(frame->data(), frame->size());
4720 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
4721 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4722 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4723 framer.error_code())
4724 << SpdyFramer::ErrorCodeToString(framer.error_code());
4725 } else {
4726 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4727 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4728 << SpdyFramer::ErrorCodeToString(framer.error_code());
4733 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
4734 if (spdy_version_ < SPDY4) {
4735 return;
4738 for (int flags = 0; flags < 256; ++flags) {
4739 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4741 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4742 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
4743 SpdyFramer framer(spdy_version_);
4744 framer.set_visitor(&visitor);
4745 framer.set_debug_visitor(&debug_visitor);
4747 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
4748 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
4749 EXPECT_CALL(visitor, OnHeaders(42, 0, false));
4750 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
4751 .WillRepeatedly(testing::Return(true));
4752 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, CONTINUATION, _, _));
4754 SpdyHeadersIR headers_ir(42);
4755 headers_ir.SetHeader("foo", "bar");
4756 headers_ir.set_end_headers(false);
4757 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
4759 SpdyContinuationIR continuation(42);
4760 continuation.SetHeader("foo", "bar");
4761 scoped_ptr<SpdySerializedFrame> frame(
4762 framer.SerializeContinuation(continuation));
4763 SetFrameFlags(frame.get(), flags, spdy_version_);
4765 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
4766 EXPECT_CALL(visitor, OnError(_));
4767 } else {
4768 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
4769 EXPECT_CALL(visitor, OnContinuation(42,
4770 flags & HEADERS_FLAG_END_HEADERS));
4771 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
4772 .WillRepeatedly(testing::Return(true));
4775 framer.ProcessInput(frame0->data(), frame0->size());
4776 framer.ProcessInput(frame->data(), frame->size());
4777 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
4778 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4779 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4780 framer.error_code())
4781 << SpdyFramer::ErrorCodeToString(framer.error_code());
4782 } else {
4783 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4784 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4785 << SpdyFramer::ErrorCodeToString(framer.error_code());
4790 TEST_P(SpdyFramerTest, EmptySynStream) {
4791 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4792 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4793 SpdyFramer framer(spdy_version_);
4794 framer.set_visitor(&visitor);
4795 framer.set_debug_visitor(&debug_visitor);
4797 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
4799 SpdySynStreamIR syn_stream(1);
4800 syn_stream.set_priority(1);
4801 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4802 // Adjust size to remove the name/value block.
4803 SetFrameLength(
4804 frame.get(),
4805 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
4806 spdy_version_);
4808 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
4809 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
4810 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
4812 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
4813 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4814 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4815 << SpdyFramer::ErrorCodeToString(framer.error_code());
4818 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
4819 const uint32 kId = 0x020304;
4820 const uint32 kFlags = 0x01;
4821 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
4823 SettingsFlagsAndId id_and_flags =
4824 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
4825 EXPECT_EQ(kId, id_and_flags.id());
4826 EXPECT_EQ(kFlags, id_and_flags.flags());
4827 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
4830 // Test handling of a RST_STREAM with out-of-bounds status codes.
4831 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
4832 const unsigned char kRstStreamStatusTooLow = 0x00;
4833 const unsigned char kRstStreamStatusTooHigh = 0xff;
4834 const unsigned char kV3RstStreamInvalid[] = {
4835 0x80, spdy_version_ch_, 0x00, 0x03,
4836 0x00, 0x00, 0x00, 0x08,
4837 0x00, 0x00, 0x00, 0x01,
4838 0x00, 0x00, 0x00, kRstStreamStatusTooLow
4840 const unsigned char kV4RstStreamInvalid[] = {
4841 0x00, 0x04, 0x03, 0x00,
4842 0x00, 0x00, 0x00, 0x01,
4843 0x00, 0x00, 0x00, kRstStreamStatusTooLow
4846 const unsigned char kV3RstStreamNumStatusCodes[] = {
4847 0x80, spdy_version_ch_, 0x00, 0x03,
4848 0x00, 0x00, 0x00, 0x08,
4849 0x00, 0x00, 0x00, 0x01,
4850 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
4852 const unsigned char kV4RstStreamNumStatusCodes[] = {
4853 0x00, 0x04, 0x03, 0x00,
4854 0x00, 0x00, 0x00, 0x01,
4855 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
4858 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4859 SpdyFramer framer(spdy_version_);
4860 framer.set_visitor(&visitor);
4862 if (IsSpdy4()) {
4863 EXPECT_CALL(visitor, OnError(_));
4864 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
4865 arraysize(kV4RstStreamInvalid));
4866 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4867 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
4868 << SpdyFramer::ErrorCodeToString(framer.error_code());
4869 } else {
4870 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
4871 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
4872 arraysize(kV3RstStreamInvalid));
4873 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4874 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4875 << SpdyFramer::ErrorCodeToString(framer.error_code());
4879 framer.Reset();
4881 if (IsSpdy4()) {
4882 EXPECT_CALL(visitor, OnError(_));
4883 framer.ProcessInput(
4884 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
4885 arraysize(kV4RstStreamNumStatusCodes));
4886 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4887 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
4888 << SpdyFramer::ErrorCodeToString(framer.error_code());
4889 } else {
4890 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
4891 framer.ProcessInput(
4892 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
4893 arraysize(kV3RstStreamNumStatusCodes));
4894 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4895 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4896 << SpdyFramer::ErrorCodeToString(framer.error_code());
4900 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
4901 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
4902 const unsigned char kV2FrameData[] = {
4903 0x80, spdy_version_ch_, 0x00, 0x07,
4904 0x00, 0x00, 0x00, 0x04,
4905 0xff, 0xff, 0xff, 0xff,
4907 const unsigned char kV3FrameData[] = {
4908 0x80, spdy_version_ch_, 0x00, 0x07,
4909 0x00, 0x00, 0x00, 0x08,
4910 0xff, 0xff, 0xff, 0xff,
4911 0x00, 0x00, 0x00, 0x00,
4913 const unsigned char kV4FrameData[] = {
4914 0x00, 0x08, 0x07, 0x00,
4915 0x00, 0x00, 0x00, 0x00,
4916 0xff, 0xff, 0xff, 0xff,
4917 0x00, 0x00, 0x00, 0x00,
4920 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4921 SpdyFramer framer(spdy_version_);
4922 framer.set_visitor(&visitor);
4924 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
4925 if (IsSpdy2()) {
4926 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
4927 arraysize(kV2FrameData));
4928 } else if (IsSpdy3()) {
4929 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
4930 arraysize(kV3FrameData));
4931 } else {
4932 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
4933 arraysize(kV4FrameData));
4935 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4936 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4937 << SpdyFramer::ErrorCodeToString(framer.error_code());
4940 TEST_P(SpdyFramerTest, OnBlocked) {
4941 if (spdy_version_ < SPDY4) {
4942 return;
4945 const SpdyStreamId kStreamId = 0;
4947 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4948 SpdyFramer framer(spdy_version_);
4949 framer.set_visitor(&visitor);
4951 EXPECT_CALL(visitor, OnBlocked(kStreamId));
4953 SpdyBlockedIR blocked_ir(0);
4954 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
4955 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
4957 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4958 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4959 << SpdyFramer::ErrorCodeToString(framer.error_code());
4962 } // namespace net