Log major user interactions with the WebsiteSettings (origin info) bubble.
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blobe7eb092c3b409180a05098a23fbacbf9e2d84aaa
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 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
86 void OnDataFrameHeader(SpdyStreamId stream_id,
87 size_t length,
88 bool fin) override {
89 LOG(FATAL) << "Unexpected data frame header";
91 void OnStreamFrameData(SpdyStreamId stream_id,
92 const char* data,
93 size_t len,
94 bool fin) override {
95 LOG(FATAL);
98 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
99 const char* header_data,
100 size_t len) override {
101 CHECK(buffer_.get() != NULL);
102 CHECK_GE(kMaxDecompressedSize, size_ + len);
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 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 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 void OnRstStream(SpdyStreamId stream_id,
144 SpdyRstStreamStatus status) override {
145 LOG(FATAL);
147 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
148 LOG(FATAL);
150 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
151 void OnSettingsEnd() override { LOG(FATAL); }
152 void OnGoAway(SpdyStreamId last_accepted_stream_id,
153 SpdyGoAwayStatus status) override {
154 LOG(FATAL);
157 void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) override {
158 SpdyFramer framer(version_);
159 framer.set_enable_compression(false);
160 SpdyHeadersIR headers(stream_id);
161 headers.set_fin(fin);
162 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
163 ResetBuffer();
164 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
165 size_ += framer.GetHeadersMinimumSize();
168 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
169 LOG(FATAL);
172 void OnPushPromise(SpdyStreamId stream_id,
173 SpdyStreamId promised_stream_id,
174 bool end) override {
175 SpdyFramer framer(version_);
176 framer.set_enable_compression(false);
177 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
178 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
179 ResetBuffer();
180 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
181 size_ += framer.GetPushPromiseMinimumSize();
184 void OnContinuation(SpdyStreamId stream_id, bool end) override {
185 LOG(FATAL);
188 void OnPriority(SpdyStreamId stream_id,
189 SpdyStreamId parent_stream_id,
190 uint8 weight,
191 bool exclusive) override {
192 // Do nothing.
195 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
196 LOG(FATAL);
197 return false;
200 char* ReleaseBuffer() {
201 CHECK(finished_);
202 return buffer_.release();
205 void OnWindowUpdate(SpdyStreamId stream_id,
206 uint32 delta_window_size) override {
207 LOG(FATAL);
210 size_t size() const {
211 CHECK(finished_);
212 return size_;
215 private:
216 SpdyMajorVersion version_;
217 scoped_ptr<char[]> buffer_;
218 size_t size_;
219 bool finished_;
221 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
224 private:
225 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
228 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
229 public SpdyFramerDebugVisitorInterface {
230 public:
231 // This is larger than our max frame size because header blocks that
232 // are too long can spill over into CONTINUATION frames.
233 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
235 explicit TestSpdyVisitor(SpdyMajorVersion version)
236 : framer_(version),
237 use_compression_(false),
238 error_count_(0),
239 syn_frame_count_(0),
240 syn_reply_frame_count_(0),
241 headers_frame_count_(0),
242 push_promise_frame_count_(0),
243 goaway_count_(0),
244 setting_count_(0),
245 settings_ack_sent_(0),
246 settings_ack_received_(0),
247 continuation_count_(0),
248 altsvc_count_(0),
249 priority_count_(0),
250 test_altsvc_ir_(0),
251 on_unknown_frame_result_(false),
252 last_window_update_stream_(0),
253 last_window_update_delta_(0),
254 last_push_promise_stream_(0),
255 last_push_promise_promised_stream_(0),
256 data_bytes_(0),
257 fin_frame_count_(0),
258 fin_opaque_data_(),
259 fin_flag_count_(0),
260 zero_length_data_frame_count_(0),
261 control_frame_header_data_count_(0),
262 zero_length_control_frame_header_data_count_(0),
263 data_frame_count_(0),
264 last_payload_len_(0),
265 last_frame_len_(0),
266 header_buffer_(new char[kDefaultHeaderBufferSize]),
267 header_buffer_length_(0),
268 header_buffer_size_(kDefaultHeaderBufferSize),
269 header_stream_id_(static_cast<SpdyStreamId>(-1)),
270 header_control_type_(DATA),
271 header_buffer_valid_(false) {}
273 void OnError(SpdyFramer* f) override {
274 LOG(INFO) << "SpdyFramer Error: "
275 << SpdyFramer::ErrorCodeToString(f->error_code());
276 ++error_count_;
279 void OnDataFrameHeader(SpdyStreamId stream_id,
280 size_t length,
281 bool fin) override {
282 ++data_frame_count_;
283 header_stream_id_ = stream_id;
286 void OnStreamFrameData(SpdyStreamId stream_id,
287 const char* data,
288 size_t len,
289 bool fin) override {
290 EXPECT_EQ(header_stream_id_, stream_id);
291 if (len == 0)
292 ++zero_length_data_frame_count_;
294 data_bytes_ += len;
295 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
296 if (len > 0) {
297 for (size_t i = 0 ; i < len; ++i) {
298 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
301 std::cerr << "\", " << len << ")\n";
304 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
305 const char* header_data,
306 size_t len) override {
307 ++control_frame_header_data_count_;
308 CHECK_EQ(header_stream_id_, stream_id);
309 if (len == 0) {
310 ++zero_length_control_frame_header_data_count_;
311 // Indicates end-of-header-block.
312 headers_.clear();
313 CHECK(header_buffer_valid_);
314 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
315 header_buffer_.get(), header_buffer_length_, &headers_);
316 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
317 << "Check failed: header_buffer_length_ == parsed_length "
318 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
319 return true;
321 const size_t available = header_buffer_size_ - header_buffer_length_;
322 if (len > available) {
323 header_buffer_valid_ = false;
324 return false;
326 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
327 header_buffer_length_ += len;
328 return true;
331 void OnSynStream(SpdyStreamId stream_id,
332 SpdyStreamId associated_stream_id,
333 SpdyPriority priority,
334 bool fin,
335 bool unidirectional) override {
336 ++syn_frame_count_;
337 if (framer_.protocol_version() > SPDY3) {
338 InitHeaderStreaming(HEADERS, stream_id);
339 } else {
340 InitHeaderStreaming(SYN_STREAM, stream_id);
342 if (fin) {
343 ++fin_flag_count_;
347 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
348 ++syn_reply_frame_count_;
349 if (framer_.protocol_version() > SPDY3) {
350 InitHeaderStreaming(HEADERS, stream_id);
351 } else {
352 InitHeaderStreaming(SYN_REPLY, stream_id);
354 if (fin) {
355 ++fin_flag_count_;
359 void OnRstStream(SpdyStreamId stream_id,
360 SpdyRstStreamStatus status) override {
361 ++fin_frame_count_;
364 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
365 if ((rst_stream_data != NULL) && (len > 0)) {
366 fin_opaque_data_ += std::string(rst_stream_data, len);
368 return true;
371 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
372 ++setting_count_;
375 void OnSettingsAck() override {
376 DCHECK_LT(SPDY3, framer_.protocol_version());
377 ++settings_ack_received_;
380 void OnSettingsEnd() override {
381 if (framer_.protocol_version() <= SPDY3) { return; }
382 ++settings_ack_sent_;
385 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
387 void OnGoAway(SpdyStreamId last_accepted_stream_id,
388 SpdyGoAwayStatus status) override {
389 ++goaway_count_;
392 void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) override {
393 ++headers_frame_count_;
394 InitHeaderStreaming(HEADERS, stream_id);
395 if (fin) {
396 ++fin_flag_count_;
400 void OnWindowUpdate(SpdyStreamId stream_id,
401 uint32 delta_window_size) override {
402 last_window_update_stream_ = stream_id;
403 last_window_update_delta_ = delta_window_size;
406 void OnPushPromise(SpdyStreamId stream_id,
407 SpdyStreamId promised_stream_id,
408 bool end) override {
409 ++push_promise_frame_count_;
410 InitHeaderStreaming(PUSH_PROMISE, stream_id);
411 last_push_promise_stream_ = stream_id;
412 last_push_promise_promised_stream_ = promised_stream_id;
415 void OnContinuation(SpdyStreamId stream_id, bool end) override {
416 ++continuation_count_;
419 void OnAltSvc(SpdyStreamId stream_id,
420 uint32 max_age,
421 uint16 port,
422 StringPiece protocol_id,
423 StringPiece host,
424 StringPiece origin) override {
425 test_altsvc_ir_.set_stream_id(stream_id);
426 test_altsvc_ir_.set_max_age(max_age);
427 test_altsvc_ir_.set_port(port);
428 test_altsvc_ir_.set_protocol_id(protocol_id.as_string());
429 test_altsvc_ir_.set_host(host.as_string());
430 if (origin.length() > 0) {
431 test_altsvc_ir_.set_origin(origin.as_string());
433 ++altsvc_count_;
436 void OnPriority(SpdyStreamId stream_id,
437 SpdyStreamId parent_stream_id,
438 uint8 weight,
439 bool exclusive) override {
440 ++priority_count_;
443 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
444 DLOG(INFO) << "Unknown frame type " << frame_type;
445 return on_unknown_frame_result_;
448 void OnSendCompressedFrame(SpdyStreamId stream_id,
449 SpdyFrameType type,
450 size_t payload_len,
451 size_t frame_len) override {
452 last_payload_len_ = payload_len;
453 last_frame_len_ = frame_len;
456 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
457 SpdyFrameType type,
458 size_t frame_len) override {
459 last_frame_len_ = frame_len;
462 // Convenience function which runs a framer simulation with particular input.
463 void SimulateInFramer(const unsigned char* input, size_t size) {
464 framer_.set_enable_compression(use_compression_);
465 framer_.set_visitor(this);
466 size_t input_remaining = size;
467 const char* input_ptr = reinterpret_cast<const char*>(input);
468 while (input_remaining > 0 &&
469 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
470 // To make the tests more interesting, we feed random (amd small) chunks
471 // into the framer. This simulates getting strange-sized reads from
472 // the socket.
473 const size_t kMaxReadSize = 32;
474 size_t bytes_read =
475 (rand() % min(input_remaining, kMaxReadSize)) + 1;
476 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
477 input_remaining -= bytes_processed;
478 input_ptr += bytes_processed;
482 void InitHeaderStreaming(SpdyFrameType header_control_type,
483 SpdyStreamId stream_id) {
484 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
485 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
486 header_control_type))) {
487 DLOG(FATAL) << "Attempted to init header streaming with "
488 << "invalid control frame type: "
489 << header_control_type;
491 memset(header_buffer_.get(), 0, header_buffer_size_);
492 header_buffer_length_ = 0;
493 header_stream_id_ = stream_id;
494 header_control_type_ = header_control_type;
495 header_buffer_valid_ = true;
496 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
499 // Override the default buffer size (16K). Call before using the framer!
500 void set_header_buffer_size(size_t header_buffer_size) {
501 header_buffer_size_ = header_buffer_size;
502 header_buffer_.reset(new char[header_buffer_size]);
505 // Largest control frame that the SPDY implementation sends, including the
506 // size of the header.
507 static size_t sent_control_frame_max_size() {
508 return SpdyFramer::kMaxControlFrameSize;
511 static size_t header_data_chunk_max_size() {
512 return SpdyFramer::kHeaderDataChunkMaxSize;
515 SpdyFramer framer_;
516 bool use_compression_;
518 // Counters from the visitor callbacks.
519 int error_count_;
520 int syn_frame_count_;
521 int syn_reply_frame_count_;
522 int headers_frame_count_;
523 int push_promise_frame_count_;
524 int goaway_count_;
525 int setting_count_;
526 int settings_ack_sent_;
527 int settings_ack_received_;
528 int continuation_count_;
529 int altsvc_count_;
530 int priority_count_;
531 SpdyAltSvcIR test_altsvc_ir_;
532 bool on_unknown_frame_result_;
533 SpdyStreamId last_window_update_stream_;
534 uint32 last_window_update_delta_;
535 SpdyStreamId last_push_promise_stream_;
536 SpdyStreamId last_push_promise_promised_stream_;
537 int data_bytes_;
538 int fin_frame_count_; // The count of RST_STREAM type frames received.
539 std::string fin_opaque_data_;
540 int fin_flag_count_; // The count of frames with the FIN flag set.
541 int zero_length_data_frame_count_; // The count of zero-length data frames.
542 int control_frame_header_data_count_; // The count of chunks received.
543 // The count of zero-length control frame header data chunks received.
544 int zero_length_control_frame_header_data_count_;
545 int data_frame_count_;
546 size_t last_payload_len_;
547 size_t last_frame_len_;
549 // Header block streaming state:
550 scoped_ptr<char[]> header_buffer_;
551 size_t header_buffer_length_;
552 size_t header_buffer_size_;
553 SpdyStreamId header_stream_id_;
554 SpdyFrameType header_control_type_;
555 bool header_buffer_valid_;
556 SpdyHeaderBlock headers_;
559 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
560 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
561 const SpdyFramer& framer) {
562 SpdyFrameReader reader(frame->data(), frame->size());
563 if (framer.protocol_version() > SPDY3) {
564 reader.Seek(3); // Seek past the frame length.
565 } else {
566 reader.Seek(2); // Seek past the frame length.
568 SpdyFrameType frame_type;
569 if (framer.protocol_version() > SPDY3) {
570 uint8 serialized_type;
571 reader.ReadUInt8(&serialized_type);
572 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
573 serialized_type);
574 DCHECK_EQ(HEADERS, frame_type);
575 uint8 flags;
576 reader.ReadUInt8(&flags);
577 if (flags & HEADERS_FLAG_PRIORITY) {
578 frame_type = SYN_STREAM;
580 } else {
581 uint16 serialized_type;
582 reader.ReadUInt16(&serialized_type);
583 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
584 serialized_type);
585 DCHECK(frame_type == HEADERS ||
586 frame_type == SYN_STREAM) << frame_type;
589 if (frame_type == SYN_STREAM) {
590 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
591 frame->size() - framer.GetSynStreamMinimumSize());
592 } else {
593 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
594 frame->size() - framer.GetHeadersMinimumSize());
598 } // namespace test
600 } // namespace net
602 using net::test::SetFrameLength;
603 using net::test::SetFrameFlags;
604 using net::test::CompareCharArraysWithHexError;
605 using net::test::SpdyFramerTestUtil;
606 using net::test::TestSpdyVisitor;
607 using net::test::GetSerializedHeaders;
609 namespace net {
611 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
612 protected:
613 void SetUp() override {
614 spdy_version_ = GetParam();
615 spdy_version_ch_ = static_cast<unsigned char>(
616 SpdyConstants::SerializeMajorVersion(spdy_version_));
619 void CompareFrame(const string& description,
620 const SpdyFrame& actual_frame,
621 const unsigned char* expected,
622 const int expected_len) {
623 const unsigned char* actual =
624 reinterpret_cast<const unsigned char*>(actual_frame.data());
625 CompareCharArraysWithHexError(
626 description, actual, actual_frame.size(), expected, expected_len);
629 void CompareFrames(const string& description,
630 const SpdyFrame& expected_frame,
631 const SpdyFrame& actual_frame) {
632 CompareCharArraysWithHexError(
633 description,
634 reinterpret_cast<const unsigned char*>(expected_frame.data()),
635 expected_frame.size(),
636 reinterpret_cast<const unsigned char*>(actual_frame.data()),
637 actual_frame.size());
640 // Returns true if the two header blocks have equivalent content.
641 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
642 const SpdyHeaderBlock* actual) {
643 if (expected->size() != actual->size()) {
644 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
645 << actual->size() << ".";
646 return false;
648 for (SpdyHeaderBlock::const_iterator it = expected->begin();
649 it != expected->end();
650 ++it) {
651 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
652 if (it2 == actual->end()) {
653 LOG(ERROR) << "Expected header name '" << it->first << "'.";
654 return false;
656 if (it->second.compare(it2->second) != 0) {
657 LOG(ERROR) << "Expected header named '" << it->first
658 << "' to have a value of '" << it->second
659 << "'. The actual value received was '" << it2->second
660 << "'.";
661 return false;
664 return true;
667 bool IsSpdy2() { return spdy_version_ == SPDY2; }
668 bool IsSpdy3() { return spdy_version_ == SPDY3; }
669 bool IsSpdy4() { return spdy_version_ == SPDY4; }
670 bool IsSpdy5() { return spdy_version_ == SPDY5; }
672 // Version of SPDY protocol to be used.
673 SpdyMajorVersion spdy_version_;
674 unsigned char spdy_version_ch_;
677 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
678 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
679 SpdyFramerTest,
680 ::testing::Values(SPDY2, SPDY3, SPDY4));
682 // Test that we ignore cookie where both name and value are empty.
683 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
684 if (spdy_version_ > SPDY3) {
685 // Not implemented for hpack.
686 return;
689 SpdyFramer framer(spdy_version_);
690 framer.set_enable_compression(true);
691 SpdyHeadersIR headers(1);
692 headers.set_priority(1);
693 headers.SetHeader("cookie",
694 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
695 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
696 EXPECT_TRUE(frame.get() != NULL);
698 TestSpdyVisitor visitor(spdy_version_);
699 visitor.use_compression_ = true;
700 visitor.SimulateInFramer(
701 reinterpret_cast<unsigned char*>(frame->data()),
702 frame->size());
704 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
705 EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
706 &visitor.headers_));
707 EXPECT_EQ(1u, visitor.headers_.size());
708 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
711 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
712 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
713 SpdyFramer framer(spdy_version_);
714 framer.set_enable_compression(false);
716 // Encode the header block into a Headers frame.
717 SpdyHeadersIR headers(1);
718 headers.set_priority(1);
719 headers.SetHeader("alpha", "beta");
720 headers.SetHeader("gamma", "charlie");
721 headers.SetHeader("cookie", "key1=value1; key2=value2");
722 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
723 EXPECT_TRUE(frame.get() != NULL);
725 TestSpdyVisitor visitor(spdy_version_);
726 visitor.use_compression_ = false;
727 visitor.SimulateInFramer(
728 reinterpret_cast<unsigned char*>(frame->data()),
729 frame->size());
731 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
732 EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
733 &visitor.headers_));
736 // Test that if there's not a full frame, we fail to parse it.
737 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
738 SpdyFramer framer(spdy_version_);
739 framer.set_enable_compression(false);
741 // Encode the header block into a Headers frame.
742 SpdyHeadersIR headers(1);
743 headers.set_priority(1);
744 headers.SetHeader("alpha", "beta");
745 headers.SetHeader("gamma", "charlie");
746 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
747 EXPECT_TRUE(frame.get() != NULL);
749 TestSpdyVisitor visitor(spdy_version_);
750 visitor.use_compression_ = false;
751 visitor.SimulateInFramer(
752 reinterpret_cast<unsigned char*>(frame->data()),
753 frame->size() - 2);
755 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
756 EXPECT_EQ(0u, visitor.headers_.size());
759 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
760 // (but don't crash).
761 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
762 if (spdy_version_ > SPDY3) {
763 return;
765 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
766 SpdyFramer framer(spdy_version_);
767 framer.set_visitor(&visitor);
769 SpdySynReplyIR syn_reply(0);
770 syn_reply.SetHeader("alpha", "beta");
771 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
772 ASSERT_TRUE(frame.get() != NULL);
774 // We shouldn't have to read the whole frame before we signal an error.
775 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
776 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
777 EXPECT_TRUE(framer.HasError());
778 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
779 << SpdyFramer::ErrorCodeToString(framer.error_code());
782 // Test that if we receive a HEADERS with stream ID zero, we signal an error
783 // (but don't crash).
784 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
785 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
786 SpdyFramer framer(spdy_version_);
787 framer.set_visitor(&visitor);
789 SpdyHeadersIR headers_ir(0);
790 headers_ir.SetHeader("alpha", "beta");
791 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
792 ASSERT_TRUE(frame.get() != NULL);
794 // We shouldn't have to read the whole frame before we signal an error.
795 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
796 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
797 EXPECT_TRUE(framer.HasError());
798 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
799 << SpdyFramer::ErrorCodeToString(framer.error_code());
802 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
803 // error (but don't crash).
804 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
805 if (spdy_version_ <= SPDY3) {
806 return;
809 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
810 SpdyFramer framer(spdy_version_);
811 framer.set_visitor(&visitor);
813 SpdyPushPromiseIR push_promise(0, 4);
814 push_promise.SetHeader("alpha", "beta");
815 scoped_ptr<SpdySerializedFrame> frame(
816 framer.SerializePushPromise(push_promise));
817 ASSERT_TRUE(frame.get() != NULL);
819 // We shouldn't have to read the whole frame before we signal an error.
820 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
821 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
822 EXPECT_TRUE(framer.HasError());
823 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
824 << SpdyFramer::ErrorCodeToString(framer.error_code());
827 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
828 // signal an error (but don't crash).
829 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
830 if (spdy_version_ <= SPDY3) {
831 return;
834 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
835 SpdyFramer framer(spdy_version_);
836 framer.set_visitor(&visitor);
838 SpdyPushPromiseIR push_promise(3, 0);
839 push_promise.SetHeader("alpha", "beta");
840 scoped_ptr<SpdySerializedFrame> frame(
841 framer.SerializePushPromise(push_promise));
842 ASSERT_TRUE(frame.get() != NULL);
844 // We shouldn't have to read the whole frame before we signal an error.
845 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
846 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
847 EXPECT_TRUE(framer.HasError());
848 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
849 << SpdyFramer::ErrorCodeToString(framer.error_code());
852 TEST_P(SpdyFramerTest, DuplicateHeader) {
853 if (spdy_version_ > SPDY3) {
854 // TODO(jgraettinger): Punting on this because we haven't determined
855 // whether duplicate HPACK headers other than Cookie are an error.
856 // If they are, this will need to be updated to use HpackOutputStream.
857 return;
859 SpdyFramer framer(spdy_version_);
860 // Frame builder with plentiful buffer size.
861 SpdyFrameBuilder frame(1024, spdy_version_);
862 if (spdy_version_ <= SPDY3) {
863 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
864 frame.WriteUInt32(3); // stream_id
865 frame.WriteUInt32(0); // associated stream id
866 frame.WriteUInt16(0); // Priority.
867 } else {
868 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
869 frame.WriteUInt32(framer.GetHighestPriority());
872 if (IsSpdy2()) {
873 frame.WriteUInt16(2); // Number of headers.
874 frame.WriteString("name");
875 frame.WriteString("value1");
876 frame.WriteString("name");
877 frame.WriteString("value2");
878 } else {
879 frame.WriteUInt32(2); // Number of headers.
880 frame.WriteStringPiece32("name");
881 frame.WriteStringPiece32("value1");
882 frame.WriteStringPiece32("name");
883 frame.WriteStringPiece32("value2");
885 // write the length
886 frame.RewriteLength(framer);
888 SpdyHeaderBlock new_headers;
889 framer.set_enable_compression(false);
890 scoped_ptr<SpdyFrame> control_frame(frame.take());
891 base::StringPiece serialized_headers =
892 GetSerializedHeaders(control_frame.get(), framer);
893 // This should fail because duplicate headers are verboten by the spec.
894 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
895 serialized_headers.size(),
896 &new_headers));
899 TEST_P(SpdyFramerTest, MultiValueHeader) {
900 SpdyFramer framer(spdy_version_);
901 // Frame builder with plentiful buffer size.
902 SpdyFrameBuilder frame(1024, spdy_version_);
903 if (spdy_version_ <= SPDY3) {
904 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
905 frame.WriteUInt32(3); // stream_id
906 frame.WriteUInt32(0); // associated stream id
907 frame.WriteUInt16(0); // Priority.
908 } else {
909 frame.BeginNewFrame(framer,
910 HEADERS,
911 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
913 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
914 frame.WriteUInt8(255); // Priority weight.
917 string value("value1\0value2", 13);
918 if (IsSpdy2()) {
919 frame.WriteUInt16(1); // Number of headers.
920 frame.WriteString("name");
921 frame.WriteString(value);
922 } else if (spdy_version_ > SPDY3) {
923 // TODO(jgraettinger): If this pattern appears again, move to test class.
924 std::map<string, string> header_set;
925 header_set["name"] = value;
926 string buffer;
927 HpackEncoder encoder(ObtainHpackHuffmanTable());
928 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
929 frame.WriteBytes(&buffer[0], buffer.size());
930 } else {
931 frame.WriteUInt32(1); // Number of headers.
932 frame.WriteStringPiece32("name");
933 frame.WriteStringPiece32(value);
935 // write the length
936 frame.RewriteLength(framer);
938 framer.set_enable_compression(false);
939 scoped_ptr<SpdyFrame> control_frame(frame.take());
941 TestSpdyVisitor visitor(spdy_version_);
942 visitor.use_compression_ = false;
943 visitor.SimulateInFramer(
944 reinterpret_cast<unsigned char*>(control_frame->data()),
945 control_frame->size());
947 EXPECT_THAT(visitor.headers_, ElementsAre(
948 Pair("name", value)));
951 TEST_P(SpdyFramerTest, BasicCompression) {
952 if (spdy_version_ > SPDY3) {
953 // Deflate compression doesn't apply to HPACK.
954 return;
956 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
957 SpdyFramer framer(spdy_version_);
958 framer.set_debug_visitor(visitor.get());
959 SpdySynStreamIR syn_stream(1);
960 syn_stream.set_priority(1);
961 syn_stream.SetHeader("server", "SpdyServer 1.0");
962 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
963 syn_stream.SetHeader("status", "200");
964 syn_stream.SetHeader("version", "HTTP/1.1");
965 syn_stream.SetHeader("content-type", "text/html");
966 syn_stream.SetHeader("content-length", "12");
967 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
968 size_t uncompressed_size1 = visitor->last_payload_len_;
969 size_t compressed_size1 =
970 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
971 if (IsSpdy2()) {
972 EXPECT_EQ(139u, uncompressed_size1);
973 #if defined(USE_SYSTEM_ZLIB)
974 EXPECT_EQ(155u, compressed_size1);
975 #else // !defined(USE_SYSTEM_ZLIB)
976 EXPECT_EQ(135u, compressed_size1);
977 #endif // !defined(USE_SYSTEM_ZLIB)
978 } else {
979 EXPECT_EQ(165u, uncompressed_size1);
980 #if defined(USE_SYSTEM_ZLIB)
981 EXPECT_EQ(181u, compressed_size1);
982 #else // !defined(USE_SYSTEM_ZLIB)
983 EXPECT_EQ(117u, compressed_size1);
984 #endif // !defined(USE_SYSTEM_ZLIB)
986 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
987 size_t uncompressed_size2 = visitor->last_payload_len_;
988 size_t compressed_size2 =
989 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
991 // Expect the second frame to be more compact than the first.
992 EXPECT_LE(frame2->size(), frame1->size());
994 // Decompress the first frame
995 scoped_ptr<SpdyFrame> frame3(
996 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
998 // Decompress the second frame
999 visitor.reset(new TestSpdyVisitor(spdy_version_));
1000 framer.set_debug_visitor(visitor.get());
1001 scoped_ptr<SpdyFrame> frame4(
1002 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1003 size_t uncompressed_size4 =
1004 frame4->size() - framer.GetSynStreamMinimumSize();
1005 size_t compressed_size4 =
1006 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1007 if (IsSpdy2()) {
1008 EXPECT_EQ(139u, uncompressed_size4);
1009 #if defined(USE_SYSTEM_ZLIB)
1010 EXPECT_EQ(149u, compressed_size4);
1011 #else // !defined(USE_SYSTEM_ZLIB)
1012 EXPECT_EQ(101u, compressed_size4);
1013 #endif // !defined(USE_SYSTEM_ZLIB)
1014 } else {
1015 EXPECT_EQ(165u, uncompressed_size4);
1016 #if defined(USE_SYSTEM_ZLIB)
1017 EXPECT_EQ(175u, compressed_size4);
1018 #else // !defined(USE_SYSTEM_ZLIB)
1019 EXPECT_EQ(102u, compressed_size4);
1020 #endif // !defined(USE_SYSTEM_ZLIB)
1023 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1024 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1025 EXPECT_EQ(compressed_size2, compressed_size4);
1027 // Expect frames 3 & 4 to be the same.
1028 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1030 // Expect frames 3 to be the same as a uncompressed frame created
1031 // from scratch.
1032 framer.set_enable_compression(false);
1033 scoped_ptr<SpdyFrame> uncompressed_frame(
1034 framer.SerializeSynStream(syn_stream));
1035 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1038 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1039 // See crbug.com/172383
1040 SpdyHeadersIR headers(1);
1041 headers.SetHeader("server", "SpdyServer 1.0");
1042 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1043 headers.SetHeader("status", "200");
1044 headers.SetHeader("version", "HTTP/1.1");
1045 headers.SetHeader("content-type", "text/html");
1046 headers.SetHeader("content-length", "12");
1047 headers.SetHeader("x-empty-header", "");
1049 SpdyFramer framer(spdy_version_);
1050 framer.set_enable_compression(true);
1051 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1054 TEST_P(SpdyFramerTest, Basic) {
1055 const unsigned char kV2Input[] = {
1056 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1057 0x00, 0x00, 0x00, 0x14,
1058 0x00, 0x00, 0x00, 0x01,
1059 0x00, 0x00, 0x00, 0x00,
1060 0x00, 0x00, 0x00, 0x01,
1061 0x00, 0x02, 'h', 'h',
1062 0x00, 0x02, 'v', 'v',
1064 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1065 0x00, 0x00, 0x00, 0x18,
1066 0x00, 0x00, 0x00, 0x01,
1067 0x00, 0x00, 0x00, 0x02,
1068 0x00, 0x02, 'h', '2',
1069 0x00, 0x02, 'v', '2',
1070 0x00, 0x02, 'h', '3',
1071 0x00, 0x02, 'v', '3',
1073 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1074 0x00, 0x00, 0x00, 0x0c,
1075 0xde, 0xad, 0xbe, 0xef,
1076 0xde, 0xad, 0xbe, 0xef,
1077 0xde, 0xad, 0xbe, 0xef,
1079 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1080 0x00, 0x00, 0x00, 0x0c,
1081 0x00, 0x00, 0x00, 0x03,
1082 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00,
1085 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1086 0x00, 0x00, 0x00, 0x08,
1087 0xde, 0xad, 0xbe, 0xef,
1088 0xde, 0xad, 0xbe, 0xef,
1090 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1091 0x00, 0x00, 0x00, 0x04,
1092 0xde, 0xad, 0xbe, 0xef,
1094 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1095 0x00, 0x00, 0x00, 0x08,
1096 0x00, 0x00, 0x00, 0x01,
1097 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1099 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1100 0x00, 0x00, 0x00, 0x00,
1102 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1103 0x00, 0x00, 0x00, 0x08,
1104 0x00, 0x00, 0x00, 0x03,
1105 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1108 const unsigned char kV3Input[] = {
1109 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1110 0x00, 0x00, 0x00, 0x1a,
1111 0x00, 0x00, 0x00, 0x01,
1112 0x00, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x01, 0x00, 0x00,
1115 0x00, 0x02, 'h', 'h',
1116 0x00, 0x00, 0x00, 0x02,
1117 'v', 'v',
1119 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1120 0x00, 0x00, 0x00, 0x20,
1121 0x00, 0x00, 0x00, 0x01,
1122 0x00, 0x00, 0x00, 0x02,
1123 0x00, 0x00, 0x00, 0x02,
1124 'h', '2',
1125 0x00, 0x00, 0x00, 0x02,
1126 'v', '2', 0x00, 0x00,
1127 0x00, 0x02, 'h', '3',
1128 0x00, 0x00, 0x00, 0x02,
1129 'v', '3',
1131 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1132 0x00, 0x00, 0x00, 0x0c,
1133 0xde, 0xad, 0xbe, 0xef,
1134 0xde, 0xad, 0xbe, 0xef,
1135 0xde, 0xad, 0xbe, 0xef,
1137 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1138 0x00, 0x00, 0x00, 0x0e,
1139 0x00, 0x00, 0x00, 0x03,
1140 0x00, 0x00, 0x00, 0x00,
1141 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1145 0x00, 0x00, 0x00, 0x08,
1146 0xde, 0xad, 0xbe, 0xef,
1147 0xde, 0xad, 0xbe, 0xef,
1149 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1150 0x00, 0x00, 0x00, 0x04,
1151 0xde, 0xad, 0xbe, 0xef,
1153 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1154 0x00, 0x00, 0x00, 0x08,
1155 0x00, 0x00, 0x00, 0x01,
1156 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1158 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1159 0x00, 0x00, 0x00, 0x00,
1161 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1162 0x00, 0x00, 0x00, 0x08,
1163 0x00, 0x00, 0x00, 0x03,
1164 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1167 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1168 // HEADERS frames with PRIORITY and END_HEADERS set.
1169 const unsigned char kV4Input[] = {
1170 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1171 0x24, 0x00, 0x00, 0x00,
1172 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1173 0x00, 0x82, // :method: GET
1175 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1176 0x04, 0x00, 0x00, 0x00, // Stream 1
1177 0x01, 0x8c, // :status: 200
1179 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1180 0x00, 0x00, 0x00, 0x00,
1181 0x01, 0xde, 0xad, 0xbe,
1182 0xef, 0xde, 0xad, 0xbe,
1183 0xef, 0xde, 0xad, 0xbe,
1184 0xef,
1186 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1187 0x24, 0x00, 0x00, 0x00,
1188 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1189 0x00, 0x82, // :method: GET
1191 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1192 0x00, 0x00, 0x00, 0x00,
1193 0x03, 0xde, 0xad, 0xbe,
1194 0xef, 0xde, 0xad, 0xbe,
1195 0xef,
1197 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1198 0x00, 0x00, 0x00, 0x00,
1199 0x01, 0xde, 0xad, 0xbe,
1200 0xef,
1202 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1203 0x00, 0x00, 0x00, 0x00,
1204 0x01, 0x00, 0x00, 0x00,
1205 0x08, // RST_STREAM_CANCEL
1207 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1208 0x00, 0x00, 0x00, 0x00,
1209 0x03,
1211 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1212 0x00, 0x00, 0x00, 0x00,
1213 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1214 0x08, 0x52, 0x45, 0x53, // opaque data
1215 0x45, 0x54, 0x53, 0x54,
1216 0x52, 0x45, 0x41, 0x4d,
1219 TestSpdyVisitor visitor(spdy_version_);
1220 if (IsSpdy2()) {
1221 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1222 } else if (IsSpdy3()) {
1223 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1224 } else {
1225 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1228 EXPECT_EQ(2, visitor.syn_frame_count_);
1229 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1230 EXPECT_EQ(1, visitor.headers_frame_count_);
1231 EXPECT_EQ(24, visitor.data_bytes_);
1233 EXPECT_EQ(0, visitor.error_count_);
1234 EXPECT_EQ(2, visitor.fin_frame_count_);
1236 if (IsSpdy4()) {
1237 base::StringPiece reset_stream = "RESETSTREAM";
1238 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1239 } else {
1240 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1243 EXPECT_EQ(0, visitor.fin_flag_count_);
1244 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1245 EXPECT_EQ(4, visitor.data_frame_count_);
1246 visitor.fin_opaque_data_.clear();
1249 // Test that the FIN flag on a data frame signifies EOF.
1250 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1251 const unsigned char kV2Input[] = {
1252 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1253 0x00, 0x00, 0x00, 0x14,
1254 0x00, 0x00, 0x00, 0x01,
1255 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x01,
1257 0x00, 0x02, 'h', 'h',
1258 0x00, 0x02, 'v', 'v',
1260 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1261 0x00, 0x00, 0x00, 0x10,
1262 0x00, 0x00, 0x00, 0x01,
1263 0x00, 0x00, 0x00, 0x01,
1264 0x00, 0x02, 'a', 'a',
1265 0x00, 0x02, 'b', 'b',
1267 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1268 0x00, 0x00, 0x00, 0x0c,
1269 0xde, 0xad, 0xbe, 0xef,
1270 0xde, 0xad, 0xbe, 0xef,
1271 0xde, 0xad, 0xbe, 0xef,
1273 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1274 0x01, 0x00, 0x00, 0x04,
1275 0xde, 0xad, 0xbe, 0xef,
1277 const unsigned char kV3Input[] = {
1278 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1279 0x00, 0x00, 0x00, 0x1a,
1280 0x00, 0x00, 0x00, 0x01,
1281 0x00, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x01, 0x00, 0x00,
1284 0x00, 0x02, 'h', 'h',
1285 0x00, 0x00, 0x00, 0x02,
1286 'v', 'v',
1288 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1289 0x00, 0x00, 0x00, 0x14,
1290 0x00, 0x00, 0x00, 0x01,
1291 0x00, 0x00, 0x00, 0x01,
1292 0x00, 0x00, 0x00, 0x02,
1293 'a', 'a', 0x00, 0x00,
1294 0x00, 0x02, 'b', 'b',
1296 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1297 0x00, 0x00, 0x00, 0x0c,
1298 0xde, 0xad, 0xbe, 0xef,
1299 0xde, 0xad, 0xbe, 0xef,
1300 0xde, 0xad, 0xbe, 0xef,
1302 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1303 0x01, 0x00, 0x00, 0x04,
1304 0xde, 0xad, 0xbe, 0xef,
1307 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1308 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1309 const unsigned char kV4Input[] = {
1310 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1311 0x24, 0x00, 0x00, 0x00, // Stream 1
1312 0x01, 0x00, 0x00, 0x00, // Priority 0
1313 0x00, 0x82, // :method: GET
1315 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1316 0x04, 0x00, 0x00, 0x00, // Stream 1
1317 0x01, 0x8c, // :status: 200
1319 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1320 0x00, 0x00, 0x00, 0x00,
1321 0x01, 0xde, 0xad, 0xbe,
1322 0xef, 0xde, 0xad, 0xbe,
1323 0xef, 0xde, 0xad, 0xbe,
1324 0xef,
1326 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1327 0x01, 0x00, 0x00, 0x00,
1328 0x01, 0xde, 0xad, 0xbe,
1329 0xef,
1332 TestSpdyVisitor visitor(spdy_version_);
1333 if (IsSpdy2()) {
1334 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1335 } else if (IsSpdy3()) {
1336 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1337 } else {
1338 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1341 EXPECT_EQ(0, visitor.error_count_);
1342 EXPECT_EQ(1, visitor.syn_frame_count_);
1343 if (IsSpdy4()) {
1344 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1345 EXPECT_EQ(1, visitor.headers_frame_count_);
1346 } else {
1347 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1348 EXPECT_EQ(0, visitor.headers_frame_count_);
1350 EXPECT_EQ(16, visitor.data_bytes_);
1351 EXPECT_EQ(0, visitor.fin_frame_count_);
1352 EXPECT_EQ(0, visitor.fin_flag_count_);
1353 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1354 EXPECT_EQ(2, visitor.data_frame_count_);
1357 // Test that the FIN flag on a SYN reply frame signifies EOF.
1358 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1359 const unsigned char kV2Input[] = {
1360 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1361 0x01, 0x00, 0x00, 0x00,
1362 0x14, 0x00, 0x00, 0x00,
1363 0x01, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00,
1365 0x01, 0x00, 0x02, 'h',
1366 'h', 0x00, 0x02, 'v',
1367 'v',
1369 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1370 0x02, 0x01, 0x00, 0x00,
1371 0x10, 0x00, 0x00, 0x00,
1372 0x01, 0x00, 0x00, 0x00,
1373 0x01, 0x00, 0x02, 'a',
1374 'a', 0x00, 0x02, 'b',
1375 'b',
1377 const unsigned char kV3Input[] = {
1378 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1379 0x01, 0x00, 0x00, 0x00,
1380 0x1a, 0x00, 0x00, 0x00,
1381 0x01, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x01, 0x00,
1384 0x00, 0x00, 0x02, 'h',
1385 'h', 0x00, 0x00, 0x00,
1386 0x02, 'v', 'v',
1388 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1389 0x02, 0x01, 0x00, 0x00,
1390 0x14, 0x00, 0x00, 0x00,
1391 0x01, 0x00, 0x00, 0x00,
1392 0x01, 0x00, 0x00, 0x00,
1393 0x02, 'a', 'a', 0x00,
1394 0x00, 0x00, 0x02, 'b',
1395 'b',
1398 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1399 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1400 const unsigned char kV4Input[] = {
1401 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1402 0x24, 0x00, 0x00, 0x00,
1403 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1404 0x00, 0x82, // :method: GET
1406 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1407 0x05, 0x00, 0x00, 0x00,
1408 0x01, 0x8c, // Stream 1, :status: 200
1411 TestSpdyVisitor visitor(spdy_version_);
1412 if (IsSpdy2()) {
1413 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1414 } else if (IsSpdy3()) {
1415 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1416 } else {
1417 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1420 EXPECT_EQ(0, visitor.error_count_);
1421 EXPECT_EQ(1, visitor.syn_frame_count_);
1422 if (IsSpdy4()) {
1423 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1424 EXPECT_EQ(1, visitor.headers_frame_count_);
1425 } else {
1426 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1427 EXPECT_EQ(0, visitor.headers_frame_count_);
1429 EXPECT_EQ(0, visitor.data_bytes_);
1430 EXPECT_EQ(0, visitor.fin_frame_count_);
1431 EXPECT_EQ(1, visitor.fin_flag_count_);
1432 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1433 EXPECT_EQ(0, visitor.data_frame_count_);
1436 TEST_P(SpdyFramerTest, HeaderCompression) {
1437 if (spdy_version_ > SPDY3) {
1438 // Deflate compression doesn't apply to HPACK.
1439 return;
1441 SpdyFramer send_framer(spdy_version_);
1442 SpdyFramer recv_framer(spdy_version_);
1444 send_framer.set_enable_compression(true);
1445 recv_framer.set_enable_compression(true);
1447 const char kHeader1[] = "header1";
1448 const char kHeader2[] = "header2";
1449 const char kHeader3[] = "header3";
1450 const char kValue1[] = "value1";
1451 const char kValue2[] = "value2";
1452 const char kValue3[] = "value3";
1454 // SYN_STREAM #1
1455 SpdyHeaderBlock block;
1456 block[kHeader1] = kValue1;
1457 block[kHeader2] = kValue2;
1458 SpdySynStreamIR syn_ir_1(1);
1459 syn_ir_1.set_name_value_block(block);
1460 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1461 EXPECT_TRUE(syn_frame_1.get() != NULL);
1463 // SYN_STREAM #2
1464 block[kHeader3] = kValue3;
1465 SpdySynStreamIR syn_stream(3);
1466 syn_stream.set_name_value_block(block);
1467 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1468 EXPECT_TRUE(syn_frame_2.get() != NULL);
1470 // Now start decompressing
1471 scoped_ptr<SpdyFrame> decompressed;
1472 scoped_ptr<SpdyFrame> uncompressed;
1473 base::StringPiece serialized_headers;
1474 SpdyHeaderBlock decompressed_headers;
1476 // Decompress SYN_STREAM #1
1477 decompressed.reset(
1478 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1479 EXPECT_TRUE(decompressed.get() != NULL);
1480 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1481 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1482 serialized_headers.size(),
1483 &decompressed_headers));
1484 EXPECT_EQ(2u, decompressed_headers.size());
1485 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1486 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1488 // Decompress SYN_STREAM #2
1489 decompressed.reset(
1490 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1491 EXPECT_TRUE(decompressed.get() != NULL);
1492 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1493 decompressed_headers.clear();
1494 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1495 serialized_headers.size(),
1496 &decompressed_headers));
1497 EXPECT_EQ(3u, decompressed_headers.size());
1498 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1499 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1500 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1503 // Verify we can decompress the stream even if handed over to the
1504 // framer 1 byte at a time.
1505 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1506 SpdyFramer send_framer(spdy_version_);
1508 send_framer.set_enable_compression(true);
1510 const char kHeader1[] = "header1";
1511 const char kHeader2[] = "header2";
1512 const char kValue1[] = "value1";
1513 const char kValue2[] = "value2";
1515 SpdyHeadersIR headers(1);
1516 headers.SetHeader(kHeader1, kValue1);
1517 headers.SetHeader(kHeader2, kValue2);
1518 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1519 EXPECT_TRUE(headers_frame.get() != NULL);
1521 const char bytes[] = "this is a test test test test test!";
1522 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1523 data_ir.set_fin(true);
1524 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1525 EXPECT_TRUE(send_frame.get() != NULL);
1527 // Run the inputs through the framer.
1528 TestSpdyVisitor visitor(spdy_version_);
1529 visitor.use_compression_ = true;
1530 const unsigned char* data;
1531 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1532 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1533 visitor.SimulateInFramer(data + idx, 1);
1534 ASSERT_EQ(0, visitor.error_count_);
1536 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1537 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1538 visitor.SimulateInFramer(data + idx, 1);
1539 ASSERT_EQ(0, visitor.error_count_);
1542 EXPECT_EQ(0, visitor.error_count_);
1543 EXPECT_EQ(0, visitor.syn_frame_count_);
1544 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1545 EXPECT_EQ(1, visitor.headers_frame_count_);
1546 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1547 EXPECT_EQ(0, visitor.fin_frame_count_);
1548 EXPECT_EQ(0, visitor.fin_flag_count_);
1549 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1550 EXPECT_EQ(1, visitor.data_frame_count_);
1553 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1554 SpdyFramer framer(spdy_version_);
1555 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1556 SpdyWindowUpdateIR(1, 0x12345678)));
1558 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1559 const unsigned char kV3FrameData[] = { // Also applies for V2.
1560 0x80, spdy_version_ch_, 0x00, 0x09,
1561 0x00, 0x00, 0x00, 0x08,
1562 0x00, 0x00, 0x00, 0x01,
1563 0x12, 0x34, 0x56, 0x78
1565 const unsigned char kV4FrameData[] = {
1566 0x00, 0x00, 0x04, 0x08,
1567 0x00, 0x00, 0x00, 0x00,
1568 0x01, 0x12, 0x34, 0x56,
1569 0x78
1572 if (IsSpdy4()) {
1573 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1574 } else {
1575 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1579 TEST_P(SpdyFramerTest, CreateDataFrame) {
1580 SpdyFramer framer(spdy_version_);
1583 const char kDescription[] = "'hello' data frame, no FIN";
1584 const unsigned char kV3FrameData[] = { // Also applies for V2.
1585 0x00, 0x00, 0x00, 0x01,
1586 0x00, 0x00, 0x00, 0x05,
1587 'h', 'e', 'l', 'l',
1590 const unsigned char kV4FrameData[] = {
1591 0x00, 0x00, 0x05, 0x00,
1592 0x00, 0x00, 0x00, 0x00,
1593 0x01, 'h', 'e', 'l',
1594 'l', 'o'
1596 const char bytes[] = "hello";
1598 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1599 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1600 if (IsSpdy4()) {
1601 CompareFrame(
1602 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1603 } else {
1604 CompareFrame(
1605 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1608 SpdyDataIR data_header_ir(1);
1609 data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
1610 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1611 data_header_ir));
1612 CompareCharArraysWithHexError(
1613 kDescription,
1614 reinterpret_cast<const unsigned char*>(frame->data()),
1615 framer.GetDataFrameMinimumSize(),
1616 IsSpdy4() ? kV4FrameData : kV3FrameData,
1617 framer.GetDataFrameMinimumSize());
1621 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1622 const unsigned char kV3FrameData[] = { // Also applies for V2.
1623 0x00, 0x00, 0x00, 0x01,
1624 0x00, 0x00, 0x00, 0x05,
1625 'h', 'e', 'l', 'l',
1629 const unsigned char kV4FrameData[] = {
1630 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1631 0x08, 0x00, 0x00, 0x00,
1632 0x01, 0xf7, // Pad length field.
1633 'h', 'e', 'l', 'l', // Data
1634 'o',
1635 // Padding of 247 0x00(s).
1636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 const char bytes[] = "hello";
1660 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1661 // 247 zeros and the pad length field make the overall padding to be 248
1662 // bytes.
1663 data_ir.set_padding_len(248);
1664 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1665 if (IsSpdy4()) {
1666 CompareFrame(
1667 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1668 } else {
1669 CompareFrame(
1670 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1673 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1674 CompareCharArraysWithHexError(
1675 kDescription,
1676 reinterpret_cast<const unsigned char*>(frame->data()),
1677 framer.GetDataFrameMinimumSize(),
1678 IsSpdy4() ? kV4FrameData : kV3FrameData,
1679 framer.GetDataFrameMinimumSize());
1683 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1684 const unsigned char kV3FrameData[] = { // Also applies for V2.
1685 0x00, 0x00, 0x00, 0x01,
1686 0x00, 0x00, 0x00, 0x05,
1687 'h', 'e', 'l', 'l',
1691 const unsigned char kV4FrameData[] = {
1692 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1693 0x08, 0x00, 0x00, 0x00,
1694 0x01, 0x07, // Pad length field.
1695 'h', 'e', 'l', 'l', // Data
1696 'o',
1697 0x00, 0x00, 0x00, 0x00, // Padding
1698 0x00, 0x00, 0x00
1700 const char bytes[] = "hello";
1702 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1703 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1704 data_ir.set_padding_len(8);
1705 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1706 if (IsSpdy4()) {
1707 CompareFrame(
1708 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1709 } else {
1710 CompareFrame(
1711 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1716 const char kDescription[] =
1717 "'hello' data frame with 1 byte padding, no FIN";
1718 const unsigned char kV3FrameData[] = { // Also applies for V2.
1719 0x00, 0x00, 0x00, 0x01,
1720 0x00, 0x00, 0x00, 0x05,
1721 'h', 'e', 'l', 'l',
1725 const unsigned char kV4FrameData[] = {
1726 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1727 0x08, 0x00, 0x00, 0x00,
1728 0x01, 0x00, // Pad length field.
1729 'h', 'e', 'l', 'l', // Data
1730 'o',
1732 const char bytes[] = "hello";
1734 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1735 // The pad length field itself is used for the 1-byte padding and no padding
1736 // payload is needed.
1737 data_ir.set_padding_len(1);
1738 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1739 if (IsSpdy4()) {
1740 CompareFrame(
1741 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1742 } else {
1743 CompareFrame(
1744 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1747 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1748 CompareCharArraysWithHexError(
1749 kDescription,
1750 reinterpret_cast<const unsigned char*>(frame->data()),
1751 framer.GetDataFrameMinimumSize(),
1752 IsSpdy4() ? kV4FrameData : kV3FrameData,
1753 framer.GetDataFrameMinimumSize());
1757 const char kDescription[] = "Data frame with negative data byte, no FIN";
1758 const unsigned char kV3FrameData[] = { // Also applies for V2.
1759 0x00, 0x00, 0x00, 0x01,
1760 0x00, 0x00, 0x00, 0x01,
1761 0xff
1763 const unsigned char kV4FrameData[] = {
1764 0x00, 0x00, 0x01, 0x00, 0x00,
1765 0x00, 0x00, 0x00, 0x01,
1766 0xff
1768 SpdyDataIR data_ir(1, StringPiece("\xff", 1));
1769 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1770 if (IsSpdy4()) {
1771 CompareFrame(
1772 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1773 } else {
1774 CompareFrame(
1775 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1780 const char kDescription[] = "'hello' data frame, with FIN";
1781 const unsigned char kV3FrameData[] = { // Also applies for V2.
1782 0x00, 0x00, 0x00, 0x01,
1783 0x01, 0x00, 0x00, 0x05,
1784 'h', 'e', 'l', 'l',
1787 const unsigned char kV4FrameData[] = {
1788 0x00, 0x00, 0x05, 0x00,
1789 0x01, 0x00, 0x00, 0x00,
1790 0x01, 'h', 'e', 'l',
1791 'l', 'o'
1793 SpdyDataIR data_ir(1, StringPiece("hello", 5));
1794 data_ir.set_fin(true);
1795 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1796 if (IsSpdy4()) {
1797 CompareFrame(
1798 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1799 } else {
1800 CompareFrame(
1801 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1806 const char kDescription[] = "Empty data frame";
1807 const unsigned char kV3FrameData[] = { // Also applies for V2.
1808 0x00, 0x00, 0x00, 0x01,
1809 0x00, 0x00, 0x00, 0x00,
1811 const unsigned char kV4FrameData[] = {
1812 0x00, 0x00, 0x00, 0x00,
1813 0x00, 0x00, 0x00, 0x00,
1814 0x01,
1816 SpdyDataIR data_ir(1, StringPiece());
1817 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1818 if (IsSpdy4()) {
1819 CompareFrame(
1820 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1821 } else {
1822 CompareFrame(
1823 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1826 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1827 CompareCharArraysWithHexError(
1828 kDescription,
1829 reinterpret_cast<const unsigned char*>(frame->data()),
1830 framer.GetDataFrameMinimumSize(),
1831 IsSpdy4() ? kV4FrameData : kV3FrameData,
1832 framer.GetDataFrameMinimumSize());
1836 const char kDescription[] = "Data frame with max stream ID";
1837 const unsigned char kV3FrameData[] = { // Also applies for V2.
1838 0x7f, 0xff, 0xff, 0xff,
1839 0x01, 0x00, 0x00, 0x05,
1840 'h', 'e', 'l', 'l',
1843 const unsigned char kV4FrameData[] = {
1844 0x00, 0x00, 0x05, 0x00,
1845 0x01, 0x7f, 0xff, 0xff,
1846 0xff, 'h', 'e', 'l',
1847 'l', 'o'
1849 SpdyDataIR data_ir(0x7fffffff, "hello");
1850 data_ir.set_fin(true);
1851 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1852 if (IsSpdy4()) {
1853 CompareFrame(
1854 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1855 } else {
1856 CompareFrame(
1857 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1861 if (!IsSpdy4()) {
1862 // This test does not apply to SPDY 4 because the max frame size is smaller
1863 // than 4MB.
1864 const char kDescription[] = "Large data frame";
1865 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1866 const string kData(kDataSize, 'A');
1867 const unsigned char kFrameHeader[] = {
1868 0x00, 0x00, 0x00, 0x01,
1869 0x01, 0x40, 0x00, 0x00,
1872 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1873 scoped_ptr<unsigned char[]> expected_frame_data(
1874 new unsigned char[kFrameSize]);
1875 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1876 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1878 SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
1879 data_ir.set_fin(true);
1880 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1881 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1885 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1886 if (!IsSpdy2() && !IsSpdy3()) {
1887 // SYN_STREAM unsupported in SPDY>3
1888 return;
1890 SpdyFramer framer(spdy_version_);
1891 framer.set_enable_compression(false);
1894 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1896 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1897 const unsigned char kV2FrameData[] = {
1898 0x80, spdy_version_ch_, 0x00, 0x01,
1899 0x00, 0x00, 0x00, 0x20,
1900 0x00, 0x00, 0x00, 0x01,
1901 0x00, 0x00, 0x00, 0x00,
1902 kPri, 0x00, 0x00, 0x02,
1903 0x00, 0x03, 'b', 'a',
1904 'r', 0x00, 0x03, 'f',
1905 'o', 'o', 0x00, 0x03,
1906 'f', 'o', 'o', 0x00,
1907 0x03, 'b', 'a', 'r'
1909 const unsigned char kV3FrameData[] = {
1910 0x80, spdy_version_ch_, 0x00, 0x01,
1911 0x00, 0x00, 0x00, 0x2a,
1912 0x00, 0x00, 0x00, 0x01,
1913 0x00, 0x00, 0x00, 0x00,
1914 kPri, 0x00, 0x00, 0x00,
1915 0x00, 0x02, 0x00, 0x00,
1916 0x00, 0x03, 'b', 'a',
1917 'r', 0x00, 0x00, 0x00,
1918 0x03, 'f', 'o', 'o',
1919 0x00, 0x00, 0x00, 0x03,
1920 'f', 'o', 'o', 0x00,
1921 0x00, 0x00, 0x03, 'b',
1922 'a', 'r'
1924 SpdySynStreamIR syn_stream(1);
1925 syn_stream.set_priority(framer.GetLowestPriority());
1926 syn_stream.SetHeader("bar", "foo");
1927 syn_stream.SetHeader("foo", "bar");
1928 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1929 if (IsSpdy2()) {
1930 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1931 } else if (IsSpdy3()) {
1932 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1933 } else {
1934 LOG(FATAL) << "Unsupported version in test.";
1939 const char kDescription[] =
1940 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1941 "max stream ID";
1943 const unsigned char kV2FrameData[] = {
1944 0x80, spdy_version_ch_, 0x00, 0x01,
1945 0x01, 0x00, 0x00, 0x1D,
1946 0x7f, 0xff, 0xff, 0xff,
1947 0x7f, 0xff, 0xff, 0xff,
1948 0x00, 0x00, 0x00, 0x02,
1949 0x00, 0x00, 0x00, 0x03,
1950 'f', 'o', 'o', 0x00,
1951 0x03, 'f', 'o', 'o',
1952 0x00, 0x03, 'b', 'a',
1955 const unsigned char kV3FrameData[] = {
1956 0x80, spdy_version_ch_, 0x00, 0x01,
1957 0x01, 0x00, 0x00, 0x27,
1958 0x7f, 0xff, 0xff, 0xff,
1959 0x7f, 0xff, 0xff, 0xff,
1960 0x00, 0x00, 0x00, 0x00,
1961 0x00, 0x02, 0x00, 0x00,
1962 0x00, 0x00, 0x00, 0x00,
1963 0x00, 0x03, 'f', 'o',
1964 'o', 0x00, 0x00, 0x00,
1965 0x03, 'f', 'o', 'o',
1966 0x00, 0x00, 0x00, 0x03,
1967 'b', 'a', 'r'
1969 SpdySynStreamIR syn_stream(0x7fffffff);
1970 syn_stream.set_associated_to_stream_id(0x7fffffff);
1971 syn_stream.set_priority(framer.GetHighestPriority());
1972 syn_stream.set_fin(true);
1973 syn_stream.SetHeader("", "foo");
1974 syn_stream.SetHeader("foo", "bar");
1975 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1976 if (IsSpdy2()) {
1977 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1978 } else if (IsSpdy3()) {
1979 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1980 } else {
1981 LOG(FATAL) << "Unsupported version in test.";
1986 const char kDescription[] =
1987 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1988 "max stream ID";
1990 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
1991 const unsigned char kV2FrameData[] = {
1992 0x80, spdy_version_ch_, 0x00, 0x01,
1993 0x01, 0x00, 0x00, 0x1D,
1994 0x7f, 0xff, 0xff, 0xff,
1995 0x7f, 0xff, 0xff, 0xff,
1996 kPri, 0x00, 0x00, 0x02,
1997 0x00, 0x03, 'b', 'a',
1998 'r', 0x00, 0x03, 'f',
1999 'o', 'o', 0x00, 0x03,
2000 'f', 'o', 'o', 0x00,
2001 0x00
2003 const unsigned char kV3FrameData[] = {
2004 0x80, spdy_version_ch_, 0x00, 0x01,
2005 0x01, 0x00, 0x00, 0x27,
2006 0x7f, 0xff, 0xff, 0xff,
2007 0x7f, 0xff, 0xff, 0xff,
2008 kPri, 0x00, 0x00, 0x00,
2009 0x00, 0x02, 0x00, 0x00,
2010 0x00, 0x03, 'b', 'a',
2011 'r', 0x00, 0x00, 0x00,
2012 0x03, 'f', 'o', 'o',
2013 0x00, 0x00, 0x00, 0x03,
2014 'f', 'o', 'o', 0x00,
2015 0x00, 0x00, 0x00
2017 SpdySynStreamIR syn_stream(0x7fffffff);
2018 syn_stream.set_associated_to_stream_id(0x7fffffff);
2019 syn_stream.set_priority(1);
2020 syn_stream.set_fin(true);
2021 syn_stream.SetHeader("bar", "foo");
2022 syn_stream.SetHeader("foo", "");
2023 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2024 if (IsSpdy2()) {
2025 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2026 } else if (IsSpdy3()) {
2027 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2028 } else {
2029 LOG(FATAL) << "Unsupported version in test.";
2034 // TODO(phajdan.jr): Clean up after we no longer need
2035 // to workaround http://crbug.com/139744.
2036 #if !defined(USE_SYSTEM_ZLIB)
2037 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2038 if (!IsSpdy2() && !IsSpdy3()) {
2039 // SYN_STREAM not supported for SPDY>3
2040 return;
2042 SpdyFramer framer(spdy_version_);
2043 framer.set_enable_compression(true);
2046 const char kDescription[] =
2047 "SYN_STREAM frame, low pri, no FIN";
2049 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2050 const unsigned char kV2FrameData[] = {
2051 0x80, spdy_version_ch_, 0x00, 0x01,
2052 0x00, 0x00, 0x00, 0x36,
2053 0x00, 0x00, 0x00, 0x01,
2054 0x00, 0x00, 0x00, 0x00,
2055 0x80, 0x00, 0x38, 0xea,
2056 0xdf, 0xa2, 0x51, 0xb2,
2057 0x62, 0x60, 0x62, 0x60,
2058 0x4e, 0x4a, 0x2c, 0x62,
2059 0x60, 0x06, 0x08, 0xa0,
2060 0xb4, 0xfc, 0x7c, 0x80,
2061 0x00, 0x62, 0x60, 0x4e,
2062 0xcb, 0xcf, 0x67, 0x60,
2063 0x06, 0x08, 0xa0, 0xa4,
2064 0xc4, 0x22, 0x80, 0x00,
2065 0x02, 0x00, 0x00, 0x00,
2066 0xff, 0xff,
2068 const unsigned char kV3FrameData[] = {
2069 0x80, spdy_version_ch_, 0x00, 0x01,
2070 0x00, 0x00, 0x00, 0x37,
2071 0x00, 0x00, 0x00, 0x01,
2072 0x00, 0x00, 0x00, 0x00,
2073 0x80, 0x00, 0x38, 0xEA,
2074 0xE3, 0xC6, 0xA7, 0xC2,
2075 0x02, 0xE5, 0x0E, 0x50,
2076 0xC2, 0x4B, 0x4A, 0x04,
2077 0xE5, 0x0B, 0x66, 0x80,
2078 0x00, 0x4A, 0xCB, 0xCF,
2079 0x07, 0x08, 0x20, 0x10,
2080 0x95, 0x96, 0x9F, 0x0F,
2081 0xA2, 0x00, 0x02, 0x28,
2082 0x29, 0xB1, 0x08, 0x20,
2083 0x80, 0x00, 0x00, 0x00,
2084 0x00, 0xFF, 0xFF,
2086 SpdySynStreamIR syn_stream(1);
2087 syn_stream.set_priority(priority);
2088 syn_stream.SetHeader("bar", "foo");
2089 syn_stream.SetHeader("foo", "bar");
2090 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2091 if (IsSpdy2()) {
2092 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2093 } else if (IsSpdy3()) {
2094 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2095 } else {
2096 LOG(FATAL) << "Unsupported version in test.";
2100 #endif // !defined(USE_SYSTEM_ZLIB)
2102 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2103 if (spdy_version_ > SPDY3) {
2104 // SYN_REPLY unsupported in SPDY>3
2105 return;
2107 SpdyFramer framer(spdy_version_);
2108 framer.set_enable_compression(false);
2111 const char kDescription[] = "SYN_REPLY frame, no FIN";
2113 const unsigned char kV2FrameData[] = {
2114 0x80, spdy_version_ch_, 0x00, 0x02,
2115 0x00, 0x00, 0x00, 0x1C,
2116 0x00, 0x00, 0x00, 0x01,
2117 0x00, 0x00, 0x00, 0x02,
2118 0x00, 0x03, 'b', 'a',
2119 'r', 0x00, 0x03, 'f',
2120 'o', 'o', 0x00, 0x03,
2121 'f', 'o', 'o', 0x00,
2122 0x03, 'b', 'a', 'r'
2124 const unsigned char kV3FrameData[] = {
2125 0x80, spdy_version_ch_, 0x00, 0x02,
2126 0x00, 0x00, 0x00, 0x24,
2127 0x00, 0x00, 0x00, 0x01,
2128 0x00, 0x00, 0x00, 0x02,
2129 0x00, 0x00, 0x00, 0x03,
2130 'b', 'a', 'r', 0x00,
2131 0x00, 0x00, 0x03, 'f',
2132 'o', 'o', 0x00, 0x00,
2133 0x00, 0x03, 'f', 'o',
2134 'o', 0x00, 0x00, 0x00,
2135 0x03, 'b', 'a', 'r'
2137 SpdySynReplyIR syn_reply(1);
2138 syn_reply.SetHeader("bar", "foo");
2139 syn_reply.SetHeader("foo", "bar");
2140 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2141 if (IsSpdy2()) {
2142 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2143 } else if (IsSpdy3()) {
2144 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2145 } else {
2146 LOG(FATAL) << "Unsupported version in test.";
2151 const char kDescription[] =
2152 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2154 const unsigned char kV2FrameData[] = {
2155 0x80, spdy_version_ch_, 0x00, 0x02,
2156 0x01, 0x00, 0x00, 0x19,
2157 0x7f, 0xff, 0xff, 0xff,
2158 0x00, 0x00, 0x00, 0x02,
2159 0x00, 0x00, 0x00, 0x03,
2160 'f', 'o', 'o', 0x00,
2161 0x03, 'f', 'o', 'o',
2162 0x00, 0x03, 'b', 'a',
2165 const unsigned char kV3FrameData[] = {
2166 0x80, spdy_version_ch_, 0x00, 0x02,
2167 0x01, 0x00, 0x00, 0x21,
2168 0x7f, 0xff, 0xff, 0xff,
2169 0x00, 0x00, 0x00, 0x02,
2170 0x00, 0x00, 0x00, 0x00,
2171 0x00, 0x00, 0x00, 0x03,
2172 'f', 'o', 'o', 0x00,
2173 0x00, 0x00, 0x03, 'f',
2174 'o', 'o', 0x00, 0x00,
2175 0x00, 0x03, 'b', 'a',
2178 SpdySynReplyIR syn_reply(0x7fffffff);
2179 syn_reply.set_fin(true);
2180 syn_reply.SetHeader("", "foo");
2181 syn_reply.SetHeader("foo", "bar");
2182 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2183 if (IsSpdy2()) {
2184 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2185 } else if (IsSpdy3()) {
2186 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2187 } else {
2188 LOG(FATAL) << "Unsupported version in test.";
2193 const char kDescription[] =
2194 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2196 const unsigned char kV2FrameData[] = {
2197 0x80, spdy_version_ch_, 0x00, 0x02,
2198 0x01, 0x00, 0x00, 0x19,
2199 0x7f, 0xff, 0xff, 0xff,
2200 0x00, 0x00, 0x00, 0x02,
2201 0x00, 0x03, 'b', 'a',
2202 'r', 0x00, 0x03, 'f',
2203 'o', 'o', 0x00, 0x03,
2204 'f', 'o', 'o', 0x00,
2205 0x00
2207 const unsigned char kV3FrameData[] = {
2208 0x80, spdy_version_ch_, 0x00, 0x02,
2209 0x01, 0x00, 0x00, 0x21,
2210 0x7f, 0xff, 0xff, 0xff,
2211 0x00, 0x00, 0x00, 0x02,
2212 0x00, 0x00, 0x00, 0x03,
2213 'b', 'a', 'r', 0x00,
2214 0x00, 0x00, 0x03, 'f',
2215 'o', 'o', 0x00, 0x00,
2216 0x00, 0x03, 'f', 'o',
2217 'o', 0x00, 0x00, 0x00,
2218 0x00
2220 SpdySynReplyIR syn_reply(0x7fffffff);
2221 syn_reply.set_fin(true);
2222 syn_reply.SetHeader("bar", "foo");
2223 syn_reply.SetHeader("foo", "");
2224 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2225 if (IsSpdy2()) {
2226 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2227 } else if (IsSpdy3()) {
2228 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2229 } else {
2230 LOG(FATAL) << "Unsupported version in test.";
2235 // TODO(phajdan.jr): Clean up after we no longer need
2236 // to workaround http://crbug.com/139744.
2237 #if !defined(USE_SYSTEM_ZLIB)
2238 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2239 if (spdy_version_ > SPDY3) {
2240 // SYN_REPLY unsupported in SPDY>3
2241 return;
2243 SpdyFramer framer(spdy_version_);
2244 framer.set_enable_compression(true);
2247 const char kDescription[] = "SYN_REPLY frame, no FIN";
2249 const unsigned char kV2FrameData[] = {
2250 0x80, spdy_version_ch_, 0x00, 0x02,
2251 0x00, 0x00, 0x00, 0x32,
2252 0x00, 0x00, 0x00, 0x01,
2253 0x00, 0x00, 0x38, 0xea,
2254 0xdf, 0xa2, 0x51, 0xb2,
2255 0x62, 0x60, 0x62, 0x60,
2256 0x4e, 0x4a, 0x2c, 0x62,
2257 0x60, 0x06, 0x08, 0xa0,
2258 0xb4, 0xfc, 0x7c, 0x80,
2259 0x00, 0x62, 0x60, 0x4e,
2260 0xcb, 0xcf, 0x67, 0x60,
2261 0x06, 0x08, 0xa0, 0xa4,
2262 0xc4, 0x22, 0x80, 0x00,
2263 0x02, 0x00, 0x00, 0x00,
2264 0xff, 0xff,
2266 const unsigned char kV3FrameData[] = {
2267 0x80, spdy_version_ch_, 0x00, 0x02,
2268 0x00, 0x00, 0x00, 0x31,
2269 0x00, 0x00, 0x00, 0x01,
2270 0x38, 0xea, 0xe3, 0xc6,
2271 0xa7, 0xc2, 0x02, 0xe5,
2272 0x0e, 0x50, 0xc2, 0x4b,
2273 0x4a, 0x04, 0xe5, 0x0b,
2274 0x66, 0x80, 0x00, 0x4a,
2275 0xcb, 0xcf, 0x07, 0x08,
2276 0x20, 0x10, 0x95, 0x96,
2277 0x9f, 0x0f, 0xa2, 0x00,
2278 0x02, 0x28, 0x29, 0xb1,
2279 0x08, 0x20, 0x80, 0x00,
2280 0x00, 0x00, 0x00, 0xff,
2281 0xff,
2283 SpdySynReplyIR syn_reply(1);
2284 syn_reply.SetHeader("bar", "foo");
2285 syn_reply.SetHeader("foo", "bar");
2286 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2287 if (IsSpdy2()) {
2288 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2289 } else if (IsSpdy3()) {
2290 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2291 } else {
2292 LOG(FATAL) << "Unsupported version in test.";
2296 #endif // !defined(USE_SYSTEM_ZLIB)
2298 TEST_P(SpdyFramerTest, CreateRstStream) {
2299 SpdyFramer framer(spdy_version_);
2302 const char kDescription[] = "RST_STREAM frame";
2303 const unsigned char kV3FrameData[] = { // Also applies for V2.
2304 0x80, spdy_version_ch_, 0x00, 0x03,
2305 0x00, 0x00, 0x00, 0x08,
2306 0x00, 0x00, 0x00, 0x01,
2307 0x00, 0x00, 0x00, 0x01,
2309 const unsigned char kV4FrameData[] = {
2310 0x00, 0x00, 0x07, 0x03,
2311 0x00, 0x00, 0x00, 0x00,
2312 0x01, 0x00, 0x00, 0x00,
2313 0x01, 0x52, 0x53, 0x54
2315 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2316 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2317 if (IsSpdy4()) {
2318 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2319 } else {
2320 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2325 const char kDescription[] = "RST_STREAM frame with max stream ID";
2326 const unsigned char kV3FrameData[] = { // Also applies for V2.
2327 0x80, spdy_version_ch_, 0x00, 0x03,
2328 0x00, 0x00, 0x00, 0x08,
2329 0x7f, 0xff, 0xff, 0xff,
2330 0x00, 0x00, 0x00, 0x01,
2332 const unsigned char kV4FrameData[] = {
2333 0x00, 0x00, 0x04, 0x03,
2334 0x00, 0x7f, 0xff, 0xff,
2335 0xff, 0x00, 0x00, 0x00,
2336 0x01,
2338 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2339 RST_STREAM_PROTOCOL_ERROR,
2340 "");
2341 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2342 if (IsSpdy4()) {
2343 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2344 } else {
2345 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2350 const char kDescription[] = "RST_STREAM frame with max status code";
2351 const unsigned char kV3FrameData[] = { // Also applies for V2.
2352 0x80, spdy_version_ch_, 0x00, 0x03,
2353 0x00, 0x00, 0x00, 0x08,
2354 0x7f, 0xff, 0xff, 0xff,
2355 0x00, 0x00, 0x00, 0x06,
2357 const unsigned char kV4FrameData[] = {
2358 0x00, 0x00, 0x04, 0x03,
2359 0x00, 0x7f, 0xff, 0xff,
2360 0xff, 0x00, 0x00, 0x00,
2361 0x06,
2363 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2364 RST_STREAM_INTERNAL_ERROR,
2365 "");
2366 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2367 if (IsSpdy4()) {
2368 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2369 } else {
2370 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2375 TEST_P(SpdyFramerTest, CreateSettings) {
2376 SpdyFramer framer(spdy_version_);
2379 const char kDescription[] = "Network byte order SETTINGS frame";
2381 const unsigned char kV2FrameData[] = {
2382 0x80, spdy_version_ch_, 0x00, 0x04,
2383 0x00, 0x00, 0x00, 0x0c,
2384 0x00, 0x00, 0x00, 0x01,
2385 0x07, 0x00, 0x00, 0x01,
2386 0x0a, 0x0b, 0x0c, 0x0d,
2388 const unsigned char kV3FrameData[] = {
2389 0x80, spdy_version_ch_, 0x00, 0x04,
2390 0x00, 0x00, 0x00, 0x0c,
2391 0x00, 0x00, 0x00, 0x01,
2392 0x01, 0x00, 0x00, 0x07,
2393 0x0a, 0x0b, 0x0c, 0x0d,
2395 const unsigned char kV4FrameData[] = {
2396 0x00, 0x00, 0x06, 0x04,
2397 0x00, 0x00, 0x00, 0x00,
2398 0x00, 0x00, 0x04, 0x0a,
2399 0x0b, 0x0c, 0x0d,
2402 uint32 kValue = 0x0a0b0c0d;
2403 SpdySettingsIR settings_ir;
2405 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2406 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2407 SettingsMap settings;
2408 settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
2409 EXPECT_EQ(kFlags, settings[kId].first);
2410 EXPECT_EQ(kValue, settings[kId].second);
2411 settings_ir.AddSetting(kId,
2412 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2413 kFlags & SETTINGS_FLAG_PERSISTED,
2414 kValue);
2416 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2417 if (IsSpdy2()) {
2418 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2419 } else if (IsSpdy3()) {
2420 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2421 } else {
2422 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2427 const char kDescription[] = "Basic SETTINGS frame";
2429 const unsigned char kV2FrameData[] = {
2430 0x80, spdy_version_ch_, 0x00, 0x04,
2431 0x00, 0x00, 0x00, 0x24,
2432 0x00, 0x00, 0x00, 0x04,
2433 0x01, 0x00, 0x00, 0x00, // 1st Setting
2434 0x00, 0x00, 0x00, 0x05,
2435 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2436 0x00, 0x00, 0x00, 0x06,
2437 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2438 0x00, 0x00, 0x00, 0x07,
2439 0x04, 0x00, 0x00, 0x00, // 4th Setting
2440 0x00, 0x00, 0x00, 0x08,
2442 const unsigned char kV3FrameData[] = {
2443 0x80, spdy_version_ch_, 0x00, 0x04,
2444 0x00, 0x00, 0x00, 0x24,
2445 0x00, 0x00, 0x00, 0x04,
2446 0x00, 0x00, 0x00, 0x01, // 1st Setting
2447 0x00, 0x00, 0x00, 0x05,
2448 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2449 0x00, 0x00, 0x00, 0x06,
2450 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2451 0x00, 0x00, 0x00, 0x07,
2452 0x00, 0x00, 0x00, 0x04, // 4th Setting
2453 0x00, 0x00, 0x00, 0x08,
2455 // These end up seemingly out of order because of the way that our internal
2456 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2457 // the wire.
2458 const unsigned char kV4FrameData[] = {
2459 0x00, 0x00, 0x18, 0x04,
2460 0x00, 0x00, 0x00, 0x00,
2461 0x00, 0x00, 0x03, // 3rd Setting
2462 0x00, 0x00, 0x00, 0x07,
2463 0x00, 0x04, // 4th Setting
2464 0x00, 0x00, 0x00, 0x08,
2465 0x00, 0x01, // 1st Setting
2466 0x00, 0x00, 0x00, 0x05,
2467 0x00, 0x02, // 2nd Setting
2468 0x00, 0x00, 0x00, 0x06,
2471 SpdySettingsIR settings_ir;
2472 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2473 false, // persist
2474 false, // persisted
2476 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2477 false, // persist
2478 false, // persisted
2480 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2481 false, // persist
2482 false, // persisted
2484 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2485 false, // persist
2486 false, // persisted
2488 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2490 if (IsSpdy2()) {
2491 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2492 } else if (IsSpdy3()) {
2493 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2494 } else {
2495 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2500 const char kDescription[] = "Empty SETTINGS frame";
2502 const unsigned char kV3FrameData[] = { // Also applies for V2.
2503 0x80, spdy_version_ch_, 0x00, 0x04,
2504 0x00, 0x00, 0x00, 0x04,
2505 0x00, 0x00, 0x00, 0x00,
2507 const unsigned char kV4FrameData[] = {
2508 0x00, 0x00, 0x00, 0x04,
2509 0x00, 0x00, 0x00, 0x00,
2510 0x00,
2512 SpdySettingsIR settings_ir;
2513 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2514 if (IsSpdy4()) {
2515 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2516 } else {
2517 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2522 TEST_P(SpdyFramerTest, CreatePingFrame) {
2523 SpdyFramer framer(spdy_version_);
2526 const char kDescription[] = "PING frame";
2527 const unsigned char kV3FrameData[] = { // Also applies for V2.
2528 0x80, spdy_version_ch_, 0x00, 0x06,
2529 0x00, 0x00, 0x00, 0x04,
2530 0x12, 0x34, 0x56, 0x78,
2532 const unsigned char kV4FrameData[] = {
2533 0x00, 0x00, 0x08, 0x06,
2534 0x00, 0x00, 0x00, 0x00,
2535 0x00, 0x12, 0x34, 0x56,
2536 0x78, 0x9a, 0xbc, 0xde,
2537 0xff,
2539 const unsigned char kV4FrameDataWithAck[] = {
2540 0x00, 0x00, 0x08, 0x06,
2541 0x01, 0x00, 0x00, 0x00,
2542 0x00, 0x12, 0x34, 0x56,
2543 0x78, 0x9a, 0xbc, 0xde,
2544 0xff,
2546 scoped_ptr<SpdyFrame> frame;
2547 if (IsSpdy4()) {
2548 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2549 SpdyPingIR ping_ir(kPingId);
2550 // Tests SpdyPingIR when the ping is not an ack.
2551 ASSERT_FALSE(ping_ir.is_ack());
2552 frame.reset(framer.SerializePing(ping_ir));
2553 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2555 // Tests SpdyPingIR when the ping is an ack.
2556 ping_ir.set_is_ack(true);
2557 frame.reset(framer.SerializePing(ping_ir));
2558 CompareFrame(kDescription, *frame,
2559 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2561 } else {
2562 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2563 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2568 TEST_P(SpdyFramerTest, CreateGoAway) {
2569 SpdyFramer framer(spdy_version_);
2572 const char kDescription[] = "GOAWAY frame";
2573 const unsigned char kV2FrameData[] = {
2574 0x80, spdy_version_ch_, 0x00, 0x07,
2575 0x00, 0x00, 0x00, 0x04,
2576 0x00, 0x00, 0x00, 0x00, // Stream Id
2578 const unsigned char kV3FrameData[] = {
2579 0x80, spdy_version_ch_, 0x00, 0x07,
2580 0x00, 0x00, 0x00, 0x08,
2581 0x00, 0x00, 0x00, 0x00, // Stream Id
2582 0x00, 0x00, 0x00, 0x00, // Status
2584 const unsigned char kV4FrameData[] = {
2585 0x00, 0x00, 0x0a, 0x07,
2586 0x00, 0x00, 0x00, 0x00,
2587 0x00, 0x00, 0x00, 0x00, // Stream id
2588 0x00, 0x00, 0x00, 0x00, // Status
2589 0x00, 0x47, 0x41, // Opaque Description
2591 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2592 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2593 if (IsSpdy2()) {
2594 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2595 } else if (IsSpdy3()) {
2596 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2597 } else {
2598 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2603 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2604 const unsigned char kV2FrameData[] = {
2605 0x80, spdy_version_ch_, 0x00, 0x07,
2606 0x00, 0x00, 0x00, 0x04,
2607 0x7f, 0xff, 0xff, 0xff, // Stream Id
2609 const unsigned char kV3FrameData[] = {
2610 0x80, spdy_version_ch_, 0x00, 0x07,
2611 0x00, 0x00, 0x00, 0x08,
2612 0x7f, 0xff, 0xff, 0xff, // Stream Id
2613 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2615 const unsigned char kV4FrameData[] = {
2616 0x00, 0x00, 0x0a, 0x07,
2617 0x00, 0x00, 0x00, 0x00,
2618 0x00, 0x7f, 0xff, 0xff, // Stream Id
2619 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2620 0x02, 0x47, 0x41, // Opaque Description
2622 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2623 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2624 if (IsSpdy2()) {
2625 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2626 } else if (IsSpdy3()) {
2627 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2628 } else {
2629 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2634 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2635 SpdyFramer framer(spdy_version_);
2636 framer.set_enable_compression(false);
2639 const char kDescription[] = "HEADERS frame, no FIN";
2641 const unsigned char kV2FrameData[] = {
2642 0x80, spdy_version_ch_, 0x00, 0x08,
2643 0x00, 0x00, 0x00, 0x1C,
2644 0x00, 0x00, 0x00, 0x01,
2645 0x00, 0x00, 0x00, 0x02,
2646 0x00, 0x03, 'b', 'a',
2647 'r', 0x00, 0x03, 'f',
2648 'o', 'o', 0x00, 0x03,
2649 'f', 'o', 'o', 0x00,
2650 0x03, 'b', 'a', 'r'
2652 const unsigned char kV3FrameData[] = {
2653 0x80, spdy_version_ch_, 0x00, 0x08,
2654 0x00, 0x00, 0x00, 0x24,
2655 0x00, 0x00, 0x00, 0x01,
2656 0x00, 0x00, 0x00, 0x02,
2657 0x00, 0x00, 0x00, 0x03,
2658 'b', 'a', 'r', 0x00,
2659 0x00, 0x00, 0x03, 'f',
2660 'o', 'o', 0x00, 0x00,
2661 0x00, 0x03, 'f', 'o',
2662 'o', 0x00, 0x00, 0x00,
2663 0x03, 'b', 'a', 'r'
2665 const unsigned char kV4FrameData[] = {
2666 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2667 0x04, 0x00, 0x00, 0x00, // Stream 1
2668 0x01, 0x00, 0x03, 0x62, // @.ba
2669 0x61, 0x72, 0x03, 0x66, // r.fo
2670 0x6f, 0x6f, 0x00, 0x03, // o@.f
2671 0x66, 0x6f, 0x6f, 0x03, // oo.b
2672 0x62, 0x61, 0x72, // ar
2674 SpdyHeadersIR headers_ir(1);
2675 headers_ir.SetHeader("bar", "foo");
2676 headers_ir.SetHeader("foo", "bar");
2677 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2678 if (IsSpdy2()) {
2679 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2680 } else if (IsSpdy3()) {
2681 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2682 } else {
2683 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2688 const char kDescription[] =
2689 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2691 const unsigned char kV2FrameData[] = {
2692 0x80, spdy_version_ch_, 0x00, 0x08,
2693 0x01, 0x00, 0x00, 0x19,
2694 0x7f, 0xff, 0xff, 0xff,
2695 0x00, 0x00, 0x00, 0x02,
2696 0x00, 0x00, 0x00, 0x03,
2697 'f', 'o', 'o', 0x00,
2698 0x03, 'f', 'o', 'o',
2699 0x00, 0x03, 'b', 'a',
2702 const unsigned char kV3FrameData[] = {
2703 0x80, spdy_version_ch_, 0x00, 0x08,
2704 0x01, 0x00, 0x00, 0x21,
2705 0x7f, 0xff, 0xff, 0xff,
2706 0x00, 0x00, 0x00, 0x02,
2707 0x00, 0x00, 0x00, 0x00,
2708 0x00, 0x00, 0x00, 0x03,
2709 'f', 'o', 'o', 0x00,
2710 0x00, 0x00, 0x03, 'f',
2711 'o', 'o', 0x00, 0x00,
2712 0x00, 0x03, 'b', 'a',
2715 const unsigned char kV4FrameData[] = {
2716 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2717 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2718 0xff, 0x00, 0x00, 0x03, // @..
2719 0x66, 0x6f, 0x6f, 0x00, // foo@
2720 0x03, 0x66, 0x6f, 0x6f, // .foo
2721 0x03, 0x62, 0x61, 0x72, // .bar
2723 SpdyHeadersIR headers_ir(0x7fffffff);
2724 headers_ir.set_fin(true);
2725 headers_ir.SetHeader("", "foo");
2726 headers_ir.SetHeader("foo", "bar");
2727 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2728 if (IsSpdy2()) {
2729 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2730 } else if (IsSpdy3()) {
2731 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2732 } else {
2733 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2738 const char kDescription[] =
2739 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2741 const unsigned char kV2FrameData[] = {
2742 0x80, spdy_version_ch_, 0x00, 0x08,
2743 0x01, 0x00, 0x00, 0x19,
2744 0x7f, 0xff, 0xff, 0xff,
2745 0x00, 0x00, 0x00, 0x02,
2746 0x00, 0x03, 'b', 'a',
2747 'r', 0x00, 0x03, 'f',
2748 'o', 'o', 0x00, 0x03,
2749 'f', 'o', 'o', 0x00,
2750 0x00
2752 const unsigned char kV3FrameData[] = {
2753 0x80, spdy_version_ch_, 0x00, 0x08,
2754 0x01, 0x00, 0x00, 0x21,
2755 0x7f, 0xff, 0xff, 0xff,
2756 0x00, 0x00, 0x00, 0x02,
2757 0x00, 0x00, 0x00, 0x03,
2758 'b', 'a', 'r', 0x00,
2759 0x00, 0x00, 0x03, 'f',
2760 'o', 'o', 0x00, 0x00,
2761 0x00, 0x03, 'f', 'o',
2762 'o', 0x00, 0x00, 0x00,
2763 0x00
2765 const unsigned char kV4FrameData[] = {
2766 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2767 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2768 0xff, 0x00, 0x03, 0x62, // @.b
2769 0x61, 0x72, 0x03, 0x66, // ar.f
2770 0x6f, 0x6f, 0x00, 0x03, // oo@.
2771 0x66, 0x6f, 0x6f, 0x00, // foo.
2773 SpdyHeadersIR headers_ir(0x7fffffff);
2774 headers_ir.set_fin(true);
2775 headers_ir.SetHeader("bar", "foo");
2776 headers_ir.SetHeader("foo", "");
2777 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2778 if (IsSpdy2()) {
2779 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2780 } else if (IsSpdy3()) {
2781 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2782 } else {
2783 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2788 const char kDescription[] =
2789 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2791 const unsigned char kV4FrameData[] = {
2792 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2793 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2794 0xff, 0x00, 0x00, 0x00, // parent stream
2795 0x00, 0xdb, // weight
2796 0x00, 0x03, 0x62, 0x61, // @.ba
2797 0x72, 0x03, 0x66, 0x6f, // r.fo
2798 0x6f, 0x00, 0x03, 0x66, // o@.f
2799 0x6f, 0x6f, 0x00, // oo.
2801 SpdyHeadersIR headers_ir(0x7fffffff);
2802 headers_ir.set_fin(true);
2803 headers_ir.set_priority(1);
2804 headers_ir.set_has_priority(true);
2805 headers_ir.SetHeader("bar", "foo");
2806 headers_ir.SetHeader("foo", "");
2807 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2808 if (IsSpdy2() || IsSpdy3()) {
2809 // HEADERS with priority not supported.
2810 } else {
2811 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2816 const char kDescription[] =
2817 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2819 const unsigned char kV4FrameData[] = {
2820 0x00, 0x00, 0x15, 0x01, // Headers
2821 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2822 // 0x7fffffff
2823 0xff, 0x05, 0x00, 0x00, // Pad length field
2824 0x03, 0x66, 0x6f, 0x6f, // .foo
2825 0x00, 0x03, 0x66, 0x6f, // @.fo
2826 0x6f, 0x03, 0x62, 0x61, // o.ba
2827 0x72, // r
2828 // Padding payload
2829 0x00, 0x00, 0x00, 0x00, 0x00,
2831 SpdyHeadersIR headers_ir(0x7fffffff);
2832 headers_ir.set_fin(true);
2833 headers_ir.SetHeader("", "foo");
2834 headers_ir.SetHeader("foo", "bar");
2835 headers_ir.set_padding_len(6);
2836 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2837 if (IsSpdy2() || IsSpdy3()) {
2838 // Padding is not supported.
2839 } else {
2840 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2845 // TODO(phajdan.jr): Clean up after we no longer need
2846 // to workaround http://crbug.com/139744.
2847 #if !defined(USE_SYSTEM_ZLIB)
2848 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2849 SpdyFramer framer(spdy_version_);
2850 framer.set_enable_compression(true);
2853 const char kDescription[] = "HEADERS frame, no FIN";
2855 const unsigned char kV2FrameData[] = {
2856 0x80, spdy_version_ch_, 0x00, 0x08,
2857 0x00, 0x00, 0x00, 0x32,
2858 0x00, 0x00, 0x00, 0x01,
2859 0x00, 0x00, 0x38, 0xea,
2860 0xdf, 0xa2, 0x51, 0xb2,
2861 0x62, 0x60, 0x62, 0x60,
2862 0x4e, 0x4a, 0x2c, 0x62,
2863 0x60, 0x06, 0x08, 0xa0,
2864 0xb4, 0xfc, 0x7c, 0x80,
2865 0x00, 0x62, 0x60, 0x4e,
2866 0xcb, 0xcf, 0x67, 0x60,
2867 0x06, 0x08, 0xa0, 0xa4,
2868 0xc4, 0x22, 0x80, 0x00,
2869 0x02, 0x00, 0x00, 0x00,
2870 0xff, 0xff,
2872 const unsigned char kV3FrameData[] = {
2873 0x80, spdy_version_ch_, 0x00, 0x08,
2874 0x00, 0x00, 0x00, 0x31,
2875 0x00, 0x00, 0x00, 0x01,
2876 0x38, 0xea, 0xe3, 0xc6,
2877 0xa7, 0xc2, 0x02, 0xe5,
2878 0x0e, 0x50, 0xc2, 0x4b,
2879 0x4a, 0x04, 0xe5, 0x0b,
2880 0x66, 0x80, 0x00, 0x4a,
2881 0xcb, 0xcf, 0x07, 0x08,
2882 0x20, 0x10, 0x95, 0x96,
2883 0x9f, 0x0f, 0xa2, 0x00,
2884 0x02, 0x28, 0x29, 0xb1,
2885 0x08, 0x20, 0x80, 0x00,
2886 0x00, 0x00, 0x00, 0xff,
2887 0xff,
2889 SpdyHeadersIR headers_ir(1);
2890 headers_ir.SetHeader("bar", "foo");
2891 headers_ir.SetHeader("foo", "bar");
2892 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2893 if (IsSpdy2()) {
2894 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2895 } else if (IsSpdy3()) {
2896 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2897 } else {
2898 // Deflate compression doesn't apply to HPACK.
2902 #endif // !defined(USE_SYSTEM_ZLIB)
2904 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
2905 SpdyFramer framer(spdy_version_);
2908 const char kDescription[] = "WINDOW_UPDATE frame";
2909 const unsigned char kV3FrameData[] = { // Also applies for V2.
2910 0x80, spdy_version_ch_, 0x00, 0x09,
2911 0x00, 0x00, 0x00, 0x08,
2912 0x00, 0x00, 0x00, 0x01,
2913 0x00, 0x00, 0x00, 0x01,
2915 const unsigned char kV4FrameData[] = {
2916 0x00, 0x00, 0x04, 0x08,
2917 0x00, 0x00, 0x00, 0x00,
2918 0x01, 0x00, 0x00, 0x00,
2919 0x01,
2921 scoped_ptr<SpdyFrame> frame(
2922 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
2923 if (IsSpdy4()) {
2924 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2925 } else {
2926 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2931 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
2932 const unsigned char kV3FrameData[] = { // Also applies for V2.
2933 0x80, spdy_version_ch_, 0x00, 0x09,
2934 0x00, 0x00, 0x00, 0x08,
2935 0x7f, 0xff, 0xff, 0xff,
2936 0x00, 0x00, 0x00, 0x01,
2938 const unsigned char kV4FrameData[] = {
2939 0x00, 0x00, 0x04, 0x08,
2940 0x00, 0x7f, 0xff, 0xff,
2941 0xff, 0x00, 0x00, 0x00,
2942 0x01,
2944 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2945 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2946 if (IsSpdy4()) {
2947 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2948 } else {
2949 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2954 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
2955 const unsigned char kV3FrameData[] = { // Also applies for V2.
2956 0x80, spdy_version_ch_, 0x00, 0x09,
2957 0x00, 0x00, 0x00, 0x08,
2958 0x00, 0x00, 0x00, 0x01,
2959 0x7f, 0xff, 0xff, 0xff,
2961 const unsigned char kV4FrameData[] = {
2962 0x00, 0x00, 0x04, 0x08,
2963 0x00, 0x00, 0x00, 0x00,
2964 0x01, 0x7f, 0xff, 0xff,
2965 0xff,
2967 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2968 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2969 if (IsSpdy4()) {
2970 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2971 } else {
2972 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2977 TEST_P(SpdyFramerTest, SerializeBlocked) {
2978 if (spdy_version_ <= SPDY3) {
2979 return;
2982 SpdyFramer framer(spdy_version_);
2984 const char kDescription[] = "BLOCKED frame";
2985 const unsigned char kType = static_cast<unsigned char>(
2986 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
2987 const unsigned char kFrameData[] = {
2988 0x00, 0x00, 0x00, kType, 0x00,
2989 0x00, 0x00, 0x00, 0x00,
2991 SpdyBlockedIR blocked_ir(0);
2992 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
2993 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2996 TEST_P(SpdyFramerTest, CreateBlocked) {
2997 if (spdy_version_ <= SPDY3) {
2998 return;
3001 SpdyFramer framer(spdy_version_);
3003 const char kDescription[] = "BLOCKED frame";
3004 const SpdyStreamId kStreamId = 3;
3006 scoped_ptr<SpdySerializedFrame> frame_serialized(
3007 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3008 SpdyBlockedIR blocked_ir(kStreamId);
3009 scoped_ptr<SpdySerializedFrame> frame_created(
3010 framer.SerializeFrame(blocked_ir));
3012 CompareFrames(kDescription, *frame_serialized, *frame_created);
3015 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3016 if (spdy_version_ <= SPDY3) {
3017 return;
3021 // Test framing PUSH_PROMISE without padding.
3022 SpdyFramer framer(spdy_version_);
3023 framer.set_enable_compression(false);
3024 const char kDescription[] = "PUSH_PROMISE frame without padding";
3026 const unsigned char kFrameData[] = {
3027 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3028 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3029 0x2a, 0x00, 0x00, 0x00, // Stream 42
3030 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3031 0x61, 0x72, 0x03, 0x66, // ar.f
3032 0x6f, 0x6f, 0x00, 0x03, // oo@.
3033 0x66, 0x6f, 0x6f, 0x03, // foo.
3034 0x62, 0x61, 0x72, // bar
3037 SpdyPushPromiseIR push_promise(42, 57);
3038 push_promise.SetHeader("bar", "foo");
3039 push_promise.SetHeader("foo", "bar");
3040 scoped_ptr<SpdySerializedFrame> frame(
3041 framer.SerializePushPromise(push_promise));
3042 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3046 // Test framing PUSH_PROMISE with one byte of padding.
3047 SpdyFramer framer(spdy_version_);
3048 framer.set_enable_compression(false);
3049 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3051 const unsigned char kFrameData[] = {
3052 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3053 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3054 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3055 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3056 0x62, 0x61, 0x72, 0x03, // bar.
3057 0x66, 0x6f, 0x6f, 0x00, // foo@
3058 0x03, 0x66, 0x6f, 0x6f, // .foo
3059 0x03, 0x62, 0x61, 0x72, // .bar
3062 SpdyPushPromiseIR push_promise(42, 57);
3063 push_promise.set_padding_len(1);
3064 push_promise.SetHeader("bar", "foo");
3065 push_promise.SetHeader("foo", "bar");
3066 scoped_ptr<SpdySerializedFrame> frame(
3067 framer.SerializePushPromise(push_promise));
3068 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3072 // Test framing PUSH_PROMISE with 177 bytes of padding.
3073 SpdyFramer framer(spdy_version_);
3074 framer.set_enable_compression(false);
3075 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3077 const unsigned char kFrameData[] = {
3078 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3079 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3080 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3081 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3082 0x62, 0x61, 0x72, 0x03, // bar.
3083 0x66, 0x6f, 0x6f, 0x00, // foo@
3084 0x03, 0x66, 0x6f, 0x6f, // .foo
3085 0x03, 0x62, 0x61, 0x72, // .bar
3086 // Padding of 176 0x00(s).
3087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3089 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3096 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3098 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3099 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3104 SpdyPushPromiseIR push_promise(42, 57);
3105 push_promise.set_padding_len(177);
3106 push_promise.SetHeader("bar", "foo");
3107 push_promise.SetHeader("foo", "bar");
3108 scoped_ptr<SpdySerializedFrame> frame(
3109 framer.SerializePushPromise(push_promise));
3110 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3114 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3115 if (spdy_version_ <= SPDY3) {
3116 return;
3119 SpdyFramer framer(spdy_version_);
3120 framer.set_enable_compression(false);
3121 const char kDescription[] = "CONTINUATION frame";
3123 const unsigned char kFrameData[] = {
3124 0x00, 0x00, 0x12, 0x09, 0x00, // CONTINUATION
3125 0x00, 0x00, 0x00, 0x2a, // Stream 42
3126 0x00, 0x03, 0x62, 0x61, // @.ba
3127 0x72, 0x03, 0x66, 0x6f, // r.fo
3128 0x6f, 0x00, 0x03, 0x66, // o@.f
3129 0x6f, 0x6f, 0x03, 0x62, // oo.b
3130 0x61, 0x72, // ar
3133 SpdyContinuationIR continuation(42);
3134 continuation.SetHeader("bar", "foo");
3135 continuation.SetHeader("foo", "bar");
3136 scoped_ptr<SpdySerializedFrame> frame(
3137 framer.SerializeContinuation(continuation));
3138 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3141 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3142 if (spdy_version_ <= SPDY3) {
3143 return;
3147 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3148 // padding, cannot hold all the data payload, which is overflowed to the
3149 // consecutive CONTINUATION frame.
3150 SpdyFramer framer(spdy_version_);
3151 framer.set_enable_compression(false);
3152 const char kDescription[] =
3153 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3155 const unsigned char kPartialPushPromiseFrameData[] = {
3156 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3157 0x08, 0x00, 0x00, 0x00, // PADDED
3158 0x2a, 0x00, 0x00, 0x00, // Stream 42
3159 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3160 0x78, 0x78, 0x78, 0x7f, // xxx.
3161 0x81, 0x07, 0x78, 0x78, // ..xx
3162 0x78, 0x78, 0x78, 0x78, // xxxx
3163 0x78, 0x78, 0x78, 0x78, // xxxx
3164 0x78, 0x78, 0x78, 0x78, // xxxx
3165 0x78, 0x78, 0x78, 0x78, // xxxx
3166 0x78, 0x78, 0x78, 0x78, // xxxx
3167 0x78, 0x78, 0x78, 0x78, // xxxx
3168 0x78, 0x78, 0x78, 0x78, // xxxx
3169 0x78, 0x78, 0x78, 0x78, // xxxx
3170 0x78, 0x78, 0x78, 0x78, // xxxx
3171 0x78, 0x78, 0x78, 0x78, // xxxx
3172 0x78, 0x78, 0x78, 0x78, // xxxx
3173 0x78, 0x78, 0x78, 0x78, // xxxx
3174 0x78, 0x78, 0x78, 0x78, // xxxx
3175 0x78, 0x78, 0x78, 0x78, // xxxx
3176 0x78, 0x78, 0x78, 0x78, // xxxx
3177 0x78, 0x78, 0x78, 0x78, // xxxx
3178 0x78, 0x78, 0x78, 0x78, // xxxx
3179 0x78, 0x78, 0x78, 0x78, // xxxx
3180 0x78, 0x78, 0x78, 0x78, // xxxx
3181 0x78, 0x78, 0x78, 0x78, // xxxx
3182 0x78, 0x78, // xx
3185 const unsigned char kContinuationFrameData[] = {
3186 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3187 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3188 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3189 0x78, 0x78, 0x78, 0x78, // xxxx
3190 0x78, 0x78, 0x78, 0x78, // xxxx
3191 0x78, 0x78, 0x78, 0x78, // xxxx
3192 0x78, 0x78, 0x78, 0x78, // xxxx
3193 0x78, 0x78,
3196 SpdyPushPromiseIR push_promise(42, 57);
3197 push_promise.set_padding_len(1);
3198 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3199 push_promise.SetHeader("xxx", big_value);
3200 scoped_ptr<SpdySerializedFrame> frame(
3201 framer.SerializePushPromise(push_promise));
3203 // The entire frame should look like below:
3204 // Name Length in Byte
3205 // ------------------------------------------- Begin of PUSH_PROMISE frame
3206 // PUSH_PROMISE header 9
3207 // Pad length field 1
3208 // Promised stream 4
3209 // Length field of key 2
3210 // Content of key 3
3211 // Length field of value 3
3212 // Part of big_value 16361
3213 // ------------------------------------------- Begin of CONTINUATION frame
3214 // CONTINUATION header 9
3215 // Remaining of big_value 22
3216 // ------------------------------------------- End
3218 // Length of everything listed above except big_value.
3219 int len_non_data_payload = 31;
3220 EXPECT_EQ(
3221 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3222 frame->size());
3224 // Partially compare the PUSH_PROMISE frame against the template.
3225 const unsigned char* frame_data =
3226 reinterpret_cast<const unsigned char*>(frame->data());
3227 CompareCharArraysWithHexError(kDescription,
3228 frame_data,
3229 arraysize(kPartialPushPromiseFrameData),
3230 kPartialPushPromiseFrameData,
3231 arraysize(kPartialPushPromiseFrameData));
3233 // Compare the CONTINUATION frame against the template.
3234 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3235 CompareCharArraysWithHexError(kDescription,
3236 frame_data,
3237 arraysize(kContinuationFrameData),
3238 kContinuationFrameData,
3239 arraysize(kContinuationFrameData));
3243 TEST_P(SpdyFramerTest, CreateAltSvc) {
3244 if (spdy_version_ <= SPDY3) {
3245 return;
3248 SpdyFramer framer(spdy_version_);
3250 const char kDescription[] = "ALTSVC frame";
3251 const unsigned char kType = static_cast<unsigned char>(
3252 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3253 const unsigned char kFrameData[] = {
3254 0x00, 0x00, 0x17, kType, 0x00,
3255 0x00, 0x00, 0x00, 0x03,
3256 0x00, 0x00, 0x00, 0x05,
3257 0x01, 0xbb, 0x00, 0x04, // Port = 443
3258 'p', 'i', 'd', '1', // Protocol-ID
3259 0x04, 'h', 'o', 's',
3260 't', 'o', 'r', 'i',
3261 'g', 'i', 'n',
3263 SpdyAltSvcIR altsvc_ir(3);
3264 altsvc_ir.set_max_age(5);
3265 altsvc_ir.set_port(443);
3266 altsvc_ir.set_protocol_id("pid1");
3267 altsvc_ir.set_host("host");
3268 altsvc_ir.set_origin("origin");
3269 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3270 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3273 TEST_P(SpdyFramerTest, CreatePriority) {
3274 if (spdy_version_ <= SPDY3) {
3275 return;
3278 SpdyFramer framer(spdy_version_);
3280 const char kDescription[] = "PRIORITY frame";
3281 const unsigned char kType = static_cast<unsigned char>(
3282 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3283 const unsigned char kFrameData[] = {
3284 0x00, 0x00, 0x05, kType, 0x00,
3285 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3286 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3287 0x10, // Weight = 16
3289 SpdyPriorityIR priority_ir(2, 1, 16, true);
3290 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3291 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3294 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3295 if (spdy_version_ > SPDY3) {
3296 // SYN_STREAM not supported in SPDY>3
3297 return;
3299 SpdyFramer framer(spdy_version_);
3300 SpdySynStreamIR syn_stream(1);
3301 syn_stream.set_priority(1);
3302 syn_stream.SetHeader("aa", "vv");
3303 syn_stream.SetHeader("bb", "ww");
3304 SpdyHeaderBlock headers = syn_stream.name_value_block();
3305 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3306 EXPECT_TRUE(control_frame.get() != NULL);
3307 TestSpdyVisitor visitor(spdy_version_);
3308 visitor.use_compression_ = true;
3309 visitor.SimulateInFramer(
3310 reinterpret_cast<unsigned char*>(control_frame->data()),
3311 control_frame->size());
3312 EXPECT_EQ(1, visitor.syn_frame_count_);
3313 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3316 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3317 if (spdy_version_ > SPDY3) {
3318 return;
3320 SpdyFramer framer(spdy_version_);
3321 SpdySynReplyIR syn_reply(1);
3322 syn_reply.SetHeader("alpha", "beta");
3323 syn_reply.SetHeader("gamma", "delta");
3324 SpdyHeaderBlock headers = syn_reply.name_value_block();
3325 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3326 EXPECT_TRUE(control_frame.get() != NULL);
3327 TestSpdyVisitor visitor(spdy_version_);
3328 visitor.use_compression_ = true;
3329 visitor.SimulateInFramer(
3330 reinterpret_cast<unsigned char*>(control_frame->data()),
3331 control_frame->size());
3332 if (IsSpdy4()) {
3333 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3334 EXPECT_EQ(1, visitor.headers_frame_count_);
3335 } else {
3336 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3337 EXPECT_EQ(0, visitor.headers_frame_count_);
3339 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3342 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3343 SpdyFramer framer(spdy_version_);
3344 SpdyHeadersIR headers_ir(1);
3345 headers_ir.SetHeader("alpha", "beta");
3346 headers_ir.SetHeader("gamma", "delta");
3347 SpdyHeaderBlock headers = headers_ir.name_value_block();
3348 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3349 EXPECT_TRUE(control_frame.get() != NULL);
3350 TestSpdyVisitor visitor(spdy_version_);
3351 visitor.use_compression_ = true;
3352 visitor.SimulateInFramer(
3353 reinterpret_cast<unsigned char*>(control_frame->data()),
3354 control_frame->size());
3355 EXPECT_EQ(1, visitor.headers_frame_count_);
3356 // control_frame_header_data_count_ depends on the random sequence
3357 // produced by rand(), so adding, removing or running single tests
3358 // alters this value. The best we can do is assert that it happens
3359 // at least twice.
3360 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3361 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3362 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3363 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3366 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3367 SpdyFramer framer(spdy_version_);
3368 SpdyHeadersIR headers_ir(1);
3369 headers_ir.set_fin(true);
3370 headers_ir.SetHeader("alpha", "beta");
3371 headers_ir.SetHeader("gamma", "delta");
3372 SpdyHeaderBlock headers = headers_ir.name_value_block();
3373 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3374 EXPECT_TRUE(control_frame.get() != NULL);
3375 TestSpdyVisitor visitor(spdy_version_);
3376 visitor.use_compression_ = true;
3377 visitor.SimulateInFramer(
3378 reinterpret_cast<unsigned char*>(control_frame->data()),
3379 control_frame->size());
3380 EXPECT_EQ(1, visitor.headers_frame_count_);
3381 // control_frame_header_data_count_ depends on the random sequence
3382 // produced by rand(), so adding, removing or running single tests
3383 // alters this value. The best we can do is assert that it happens
3384 // at least twice.
3385 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3386 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3387 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3388 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3391 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3392 if (spdy_version_ > SPDY3) {
3393 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3394 return;
3396 // First find the size of the header value in order to just reach the control
3397 // frame max size.
3398 SpdyFramer framer(spdy_version_);
3399 framer.set_enable_compression(false);
3400 SpdySynStreamIR syn_stream(1);
3401 syn_stream.set_priority(1);
3402 syn_stream.SetHeader("aa", "");
3403 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3404 const size_t kBigValueSize =
3405 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3407 // Create a frame at exactly that size.
3408 string big_value(kBigValueSize, 'x');
3409 syn_stream.SetHeader("aa", big_value);
3410 control_frame.reset(framer.SerializeSynStream(syn_stream));
3411 EXPECT_TRUE(control_frame.get() != NULL);
3412 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3413 control_frame->size());
3415 TestSpdyVisitor visitor(spdy_version_);
3416 visitor.SimulateInFramer(
3417 reinterpret_cast<unsigned char*>(control_frame->data()),
3418 control_frame->size());
3419 EXPECT_TRUE(visitor.header_buffer_valid_);
3420 EXPECT_EQ(0, visitor.error_count_);
3421 EXPECT_EQ(1, visitor.syn_frame_count_);
3422 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3423 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3424 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3427 // This test is disabled because Chromium is willing to accept control frames up
3428 // to the maximum size allowed by the specification, and SpdyFrameBuilder is not
3429 // capable of building larger frames.
3430 TEST_P(SpdyFramerTest, DISABLED_ControlFrameTooLarge) {
3431 if (spdy_version_ > SPDY3) {
3432 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3433 return;
3435 // First find the size of the header value in order to just reach the control
3436 // frame max size.
3437 SpdyFramer framer(spdy_version_);
3438 framer.set_enable_compression(false);
3439 SpdySynStreamIR syn_stream(1);
3440 syn_stream.SetHeader("aa", "");
3441 syn_stream.set_priority(1);
3442 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3443 const size_t kBigValueSize =
3444 SpdyConstants::GetFrameMaximumSize(spdy_version_) -
3445 control_frame->size() + 1;
3447 // Create a frame at exatly that size.
3448 string big_value(kBigValueSize, 'x');
3449 syn_stream.SetHeader("aa", big_value);
3450 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3451 // neither support that in Chromium, nor do we use the same DFATAL (see
3452 // SpdyFrameBuilder::WriteFramePrefix()).
3453 control_frame.reset(framer.SerializeSynStream(syn_stream));
3455 EXPECT_TRUE(control_frame.get() != NULL);
3456 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_) + 1,
3457 control_frame->size());
3459 TestSpdyVisitor visitor(spdy_version_);
3460 visitor.SimulateInFramer(
3461 reinterpret_cast<unsigned char*>(control_frame->data()),
3462 control_frame->size());
3463 EXPECT_FALSE(visitor.header_buffer_valid_);
3464 EXPECT_EQ(1, visitor.error_count_);
3465 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3466 visitor.framer_.error_code())
3467 << SpdyFramer::ErrorCodeToString(framer.error_code());
3468 EXPECT_EQ(0, visitor.syn_frame_count_);
3469 EXPECT_EQ(0u, visitor.header_buffer_length_);
3472 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3473 if (spdy_version_ <= SPDY3) {
3474 return;
3476 SpdyFramer framer(spdy_version_);
3477 framer.set_enable_compression(false);
3478 SpdyHeadersIR headers(1);
3479 headers.set_padding_len(256);
3481 // Exact payload length will change with HPACK, but this should be long
3482 // enough to cause an overflow.
3483 const size_t kBigValueSize = kControlFrameSizeLimit;
3484 string big_value(kBigValueSize, 'x');
3485 headers.SetHeader("aa", big_value);
3486 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3487 EXPECT_TRUE(control_frame.get() != NULL);
3488 EXPECT_GT(control_frame->size(),
3489 TestSpdyVisitor::sent_control_frame_max_size());
3491 TestSpdyVisitor visitor(spdy_version_);
3492 visitor.SimulateInFramer(
3493 reinterpret_cast<unsigned char*>(control_frame->data()),
3494 control_frame->size());
3495 EXPECT_TRUE(visitor.header_buffer_valid_);
3496 EXPECT_EQ(0, visitor.error_count_);
3497 EXPECT_EQ(1, visitor.headers_frame_count_);
3498 EXPECT_EQ(16, visitor.continuation_count_);
3499 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3502 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3503 if (spdy_version_ <= SPDY3) {
3504 return;
3506 SpdyFramer framer(spdy_version_);
3507 framer.set_enable_compression(false);
3508 SpdyPushPromiseIR push_promise(1, 2);
3509 push_promise.set_padding_len(256);
3511 // Exact payload length will change with HPACK, but this should be long
3512 // enough to cause an overflow.
3513 const size_t kBigValueSize = kControlFrameSizeLimit;
3514 string big_value(kBigValueSize, 'x');
3515 push_promise.SetHeader("aa", big_value);
3516 scoped_ptr<SpdyFrame> control_frame(
3517 framer.SerializePushPromise(push_promise));
3518 EXPECT_TRUE(control_frame.get() != NULL);
3519 EXPECT_GT(control_frame->size(),
3520 TestSpdyVisitor::sent_control_frame_max_size());
3522 TestSpdyVisitor visitor(spdy_version_);
3523 visitor.SimulateInFramer(
3524 reinterpret_cast<unsigned char*>(control_frame->data()),
3525 control_frame->size());
3526 EXPECT_TRUE(visitor.header_buffer_valid_);
3527 EXPECT_EQ(0, visitor.error_count_);
3528 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3529 EXPECT_EQ(16, visitor.continuation_count_);
3530 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3533 // Check that the framer stops delivering header data chunks once the visitor
3534 // declares it doesn't want any more. This is important to guard against
3535 // "zip bomb" types of attacks.
3536 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3537 const size_t kHeaderBufferChunks = 4;
3538 const size_t kHeaderBufferSize =
3539 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3540 const size_t kBigValueSize = kHeaderBufferSize * 2;
3541 string big_value(kBigValueSize, 'x');
3542 SpdyFramer framer(spdy_version_);
3543 SpdyHeadersIR headers(1);
3544 headers.set_priority(1);
3545 headers.set_fin(true);
3546 headers.SetHeader("aa", big_value);
3547 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3548 EXPECT_TRUE(control_frame.get() != NULL);
3549 TestSpdyVisitor visitor(spdy_version_);
3550 visitor.set_header_buffer_size(kHeaderBufferSize);
3551 visitor.use_compression_ = true;
3552 visitor.SimulateInFramer(
3553 reinterpret_cast<unsigned char*>(control_frame->data()),
3554 control_frame->size());
3555 EXPECT_FALSE(visitor.header_buffer_valid_);
3556 EXPECT_EQ(1, visitor.error_count_);
3557 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3558 visitor.framer_.error_code())
3559 << SpdyFramer::ErrorCodeToString(framer.error_code());
3561 // The framer should have stoped delivering chunks after the visitor
3562 // signaled "stop" by returning false from OnControlFrameHeaderData().
3564 // control_frame_header_data_count_ depends on the random sequence
3565 // produced by rand(), so adding, removing or running single tests
3566 // alters this value. The best we can do is assert that it happens
3567 // at least kHeaderBufferChunks + 1.
3568 EXPECT_LE(kHeaderBufferChunks + 1,
3569 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3570 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3572 // The framer should not have sent half-close to the visitor.
3573 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3576 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3577 if (spdy_version_ > SPDY3) {
3578 // Deflate compression doesn't apply to HPACK.
3579 return;
3581 SpdyFramer framer(spdy_version_);
3582 framer.set_enable_compression(false);
3583 // Construct a SYN_STREAM control frame without compressing the header block,
3584 // and have the framer try to decompress it. This will cause the framer to
3585 // deal with a decompression error.
3586 SpdySynStreamIR syn_stream(1);
3587 syn_stream.set_priority(1);
3588 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3589 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3590 TestSpdyVisitor visitor(spdy_version_);
3591 visitor.use_compression_ = true;
3592 visitor.SimulateInFramer(
3593 reinterpret_cast<unsigned char*>(control_frame->data()),
3594 control_frame->size());
3595 EXPECT_EQ(1, visitor.error_count_);
3596 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3597 << SpdyFramer::ErrorCodeToString(framer.error_code());
3598 EXPECT_EQ(0u, visitor.header_buffer_length_);
3601 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3602 SpdyFramer framer(spdy_version_);
3603 // Create a GoAway frame that has a few extra bytes at the end.
3604 // We create enough overhead to overflow the framer's control frame buffer.
3605 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize);
3606 const unsigned char length = 1 + SpdyFramer::kControlFrameBufferSize;
3607 const unsigned char kV3FrameData[] = { // Also applies for V2.
3608 0x80, spdy_version_ch_, 0x00, 0x07,
3609 0x00, 0x00, 0x00, length,
3610 0x00, 0x00, 0x00, 0x00, // Stream ID
3611 0x00, 0x00, 0x00, 0x00, // Status
3614 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3615 // since it may carry opaque data. Verify that minimal length is tested.
3616 const unsigned char less_than_min_length =
3617 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3618 const unsigned char kV4FrameData[] = {
3619 0x00, 0x00, static_cast<uint8>(less_than_min_length), 0x07,
3620 0x00, 0x00, 0x00, 0x00,
3621 0x00, 0x00, 0x00, 0x00, // Stream Id
3622 0x00, 0x00, 0x00, 0x00, // Status
3623 0x00,
3625 const size_t pad_length =
3626 length + framer.GetControlFrameHeaderSize() -
3627 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3628 string pad('A', pad_length);
3629 TestSpdyVisitor visitor(spdy_version_);
3631 if (IsSpdy4()) {
3632 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3633 } else {
3634 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3636 visitor.SimulateInFramer(
3637 reinterpret_cast<const unsigned char*>(pad.c_str()),
3638 pad.length());
3640 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3641 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3642 visitor.framer_.error_code())
3643 << SpdyFramer::ErrorCodeToString(framer.error_code());
3644 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3647 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3648 SpdyFramer framer(spdy_version_);
3649 SpdySettingsIR settings_ir;
3650 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3651 SetFrameLength(control_frame.get(), 0, spdy_version_);
3652 TestSpdyVisitor visitor(spdy_version_);
3653 visitor.use_compression_ = false;
3654 visitor.SimulateInFramer(
3655 reinterpret_cast<unsigned char*>(control_frame->data()),
3656 framer.GetControlFrameHeaderSize());
3657 if (spdy_version_ <= SPDY3) {
3658 // Should generate an error, since zero-len settings frames are unsupported.
3659 EXPECT_EQ(1, visitor.error_count_);
3660 } else {
3661 // Zero-len settings frames are permitted as of SPDY 4.
3662 EXPECT_EQ(0, visitor.error_count_);
3666 // Tests handling of SETTINGS frames with invalid length.
3667 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3668 SpdyFramer framer(spdy_version_);
3669 SpdySettingsIR settings_ir;
3671 // Add a setting to pad the frame so that we don't get a buffer overflow when
3672 // calling SimulateInFramer() below.
3673 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3674 false,
3675 false,
3676 0x00000002);
3677 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3678 const size_t kNewLength = 14;
3679 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3680 TestSpdyVisitor visitor(spdy_version_);
3681 visitor.use_compression_ = false;
3682 visitor.SimulateInFramer(
3683 reinterpret_cast<unsigned char*>(control_frame->data()),
3684 framer.GetControlFrameHeaderSize() + kNewLength);
3685 // Should generate an error, since its not possible to have a
3686 // settings frame of length kNewLength.
3687 EXPECT_EQ(1, visitor.error_count_);
3690 // Tests handling of SETTINGS frames larger than the frame buffer size.
3691 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3692 SpdyFramer framer(spdy_version_);
3693 SpdySettingsIR settings_ir;
3694 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3695 false, // persist
3696 false, // persisted
3698 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3699 false, // persist
3700 false, // persisted
3702 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3703 false, // persist
3704 false, // persisted
3707 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3708 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3709 control_frame->size());
3710 TestSpdyVisitor visitor(spdy_version_);
3711 visitor.use_compression_ = false;
3713 // Read all at once.
3714 visitor.SimulateInFramer(
3715 reinterpret_cast<unsigned char*>(control_frame->data()),
3716 control_frame->size());
3717 EXPECT_EQ(0, visitor.error_count_);
3718 EXPECT_EQ(3, visitor.setting_count_);
3719 if (spdy_version_ > SPDY3) {
3720 EXPECT_EQ(1, visitor.settings_ack_sent_);
3723 // Read data in small chunks.
3724 size_t framed_data = 0;
3725 size_t unframed_data = control_frame->size();
3726 size_t kReadChunkSize = 5; // Read five bytes at a time.
3727 while (unframed_data > 0) {
3728 size_t to_read = min(kReadChunkSize, unframed_data);
3729 visitor.SimulateInFramer(
3730 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3731 to_read);
3732 unframed_data -= to_read;
3733 framed_data += to_read;
3735 EXPECT_EQ(0, visitor.error_count_);
3736 EXPECT_EQ(3 * 2, visitor.setting_count_);
3737 if (spdy_version_ > SPDY3) {
3738 EXPECT_EQ(2, visitor.settings_ack_sent_);
3742 // Tests handling of SETTINGS frame with duplicate entries.
3743 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3744 SpdyFramer framer(spdy_version_);
3746 const unsigned char kV2FrameData[] = {
3747 0x80, spdy_version_ch_, 0x00, 0x04,
3748 0x00, 0x00, 0x00, 0x1C,
3749 0x00, 0x00, 0x00, 0x03,
3750 0x01, 0x00, 0x00, 0x00, // 1st Setting
3751 0x00, 0x00, 0x00, 0x02,
3752 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3753 0x00, 0x00, 0x00, 0x03,
3754 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3755 0x00, 0x00, 0x00, 0x03,
3757 const unsigned char kV3FrameData[] = {
3758 0x80, spdy_version_ch_, 0x00, 0x04,
3759 0x00, 0x00, 0x00, 0x1C,
3760 0x00, 0x00, 0x00, 0x03,
3761 0x00, 0x00, 0x00, 0x01, // 1st Setting
3762 0x00, 0x00, 0x00, 0x02,
3763 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3764 0x00, 0x00, 0x00, 0x03,
3765 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3766 0x00, 0x00, 0x00, 0x03,
3768 const unsigned char kV4FrameData[] = {
3769 0x00, 0x00, 0x12, 0x04,
3770 0x00, 0x00, 0x00, 0x00,
3771 0x00, 0x00, 0x01, // 1st Setting
3772 0x00, 0x00, 0x00, 0x02,
3773 0x00, 0x01, // 2nd (duplicate) Setting
3774 0x00, 0x00, 0x00, 0x03,
3775 0x00, 0x03, // 3rd (unprocessed) Setting
3776 0x00, 0x00, 0x00, 0x03,
3779 TestSpdyVisitor visitor(spdy_version_);
3780 visitor.use_compression_ = false;
3781 if (IsSpdy2()) {
3782 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3783 } else if (IsSpdy3()) {
3784 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3785 } else {
3786 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3789 if (!IsSpdy4()) {
3790 EXPECT_EQ(1, visitor.setting_count_);
3791 EXPECT_EQ(1, visitor.error_count_);
3792 } else {
3793 // In SPDY 4+, duplicate settings are allowed;
3794 // each setting replaces the previous value for that setting.
3795 EXPECT_EQ(3, visitor.setting_count_);
3796 EXPECT_EQ(0, visitor.error_count_);
3797 EXPECT_EQ(1, visitor.settings_ack_sent_);
3801 // Tests handling of SETTINGS frame with a setting we don't recognize.
3802 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3803 SpdyFramer framer(spdy_version_);
3805 const unsigned char kV2FrameData[] = {
3806 0x80, spdy_version_ch_, 0x00, 0x04,
3807 0x00, 0x00, 0x00, 0x1C,
3808 0x00, 0x00, 0x00, 0x01,
3809 0x10, 0x00, 0x00, 0x00, // 1st Setting
3810 0x00, 0x00, 0x00, 0x02,
3812 const unsigned char kV3FrameData[] = {
3813 0x80, spdy_version_ch_, 0x00, 0x04,
3814 0x00, 0x00, 0x00, 0x1C,
3815 0x00, 0x00, 0x00, 0x01,
3816 0x00, 0x00, 0x00, 0x10, // 1st Setting
3817 0x00, 0x00, 0x00, 0x02,
3819 const unsigned char kV4FrameData[] = {
3820 0x00, 0x00, 0x06, 0x04,
3821 0x00, 0x00, 0x00, 0x00,
3822 0x00, 0x00, 0x10, // 1st Setting
3823 0x00, 0x00, 0x00, 0x02,
3826 TestSpdyVisitor visitor(spdy_version_);
3827 visitor.use_compression_ = false;
3828 if (IsSpdy2()) {
3829 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3830 } else if (IsSpdy3()) {
3831 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3832 } else {
3833 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3836 if (!IsSpdy4()) {
3837 EXPECT_EQ(0, visitor.setting_count_);
3838 EXPECT_EQ(1, visitor.error_count_);
3839 } else {
3840 // In SPDY 4+, we ignore unknown settings because of extensions.
3841 EXPECT_EQ(0, visitor.setting_count_);
3842 EXPECT_EQ(0, visitor.error_count_);
3846 // Tests handling of SETTINGS frame with entries out of order.
3847 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
3848 SpdyFramer framer(spdy_version_);
3850 const unsigned char kV2FrameData[] = {
3851 0x80, spdy_version_ch_, 0x00, 0x04,
3852 0x00, 0x00, 0x00, 0x1C,
3853 0x00, 0x00, 0x00, 0x03,
3854 0x02, 0x00, 0x00, 0x00, // 1st Setting
3855 0x00, 0x00, 0x00, 0x02,
3856 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
3857 0x00, 0x00, 0x00, 0x03,
3858 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3859 0x00, 0x00, 0x00, 0x03,
3861 const unsigned char kV3FrameData[] = {
3862 0x80, spdy_version_ch_, 0x00, 0x04,
3863 0x00, 0x00, 0x00, 0x1C,
3864 0x00, 0x00, 0x00, 0x03,
3865 0x00, 0x00, 0x00, 0x02, // 1st Setting
3866 0x00, 0x00, 0x00, 0x02,
3867 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3868 0x00, 0x00, 0x00, 0x03,
3869 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3870 0x00, 0x00, 0x00, 0x03,
3872 const unsigned char kV4FrameData[] = {
3873 0x00, 0x00, 0x12, 0x04,
3874 0x00, 0x00, 0x00, 0x00,
3875 0x00, 0x00, 0x02, // 1st Setting
3876 0x00, 0x00, 0x00, 0x02,
3877 0x00, 0x01, // 2nd (out of order) Setting
3878 0x00, 0x00, 0x00, 0x03,
3879 0x00, 0x03, // 3rd (unprocessed) Setting
3880 0x00, 0x00, 0x00, 0x03,
3883 TestSpdyVisitor visitor(spdy_version_);
3884 visitor.use_compression_ = false;
3885 if (IsSpdy2()) {
3886 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3887 } else if (IsSpdy3()) {
3888 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3889 } else {
3890 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3893 if (!IsSpdy4()) {
3894 EXPECT_EQ(1, visitor.setting_count_);
3895 EXPECT_EQ(1, visitor.error_count_);
3896 } else {
3897 // In SPDY 4+, settings are allowed in any order.
3898 EXPECT_EQ(3, visitor.setting_count_);
3899 EXPECT_EQ(0, visitor.error_count_);
3903 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
3904 if (spdy_version_ <= SPDY3) {
3905 return;
3907 SpdyFramer framer(spdy_version_);
3909 const unsigned char kFrameData[] = {
3910 0x00, 0x00, 0x00, 0x04, 0x01,
3911 0x00, 0x00, 0x00, 0x00,
3914 TestSpdyVisitor visitor(spdy_version_);
3915 visitor.use_compression_ = false;
3916 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
3918 EXPECT_EQ(0, visitor.error_count_);
3919 EXPECT_EQ(0, visitor.setting_count_);
3920 EXPECT_EQ(1, visitor.settings_ack_received_);
3923 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
3924 if (spdy_version_ <= SPDY3) {
3925 return;
3928 const int kPaddingLen = 119;
3929 const char data_payload[] = "hello";
3931 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3932 SpdyFramer framer(spdy_version_);
3933 framer.set_visitor(&visitor);
3935 SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
3936 data_ir.set_padding_len(kPaddingLen);
3937 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
3938 ASSERT_TRUE(frame.get() != NULL);
3940 int bytes_consumed = 0;
3942 // Send the frame header.
3943 EXPECT_CALL(visitor, OnDataFrameHeader(1,
3944 kPaddingLen + strlen(data_payload),
3945 false));
3946 CHECK_EQ(framer.GetDataFrameMinimumSize(),
3947 framer.ProcessInput(frame->data(),
3948 framer.GetDataFrameMinimumSize()));
3949 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
3950 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3951 bytes_consumed += framer.GetDataFrameMinimumSize();
3953 // Send the padding length field.
3954 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
3955 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3956 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3957 bytes_consumed += 1;
3959 // Send the first two bytes of the data payload, i.e., "he".
3960 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
3961 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
3962 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3963 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3964 bytes_consumed += 2;
3966 // Send the rest three bytes of the data payload, i.e., "llo".
3967 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
3968 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
3969 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3970 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3971 bytes_consumed += 3;
3973 // Send the first 100 bytes of the padding payload.
3974 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false));
3975 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
3976 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3977 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3978 bytes_consumed += 100;
3980 // Send rest of the padding payload.
3981 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 18, false));
3982 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
3983 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
3984 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3987 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
3988 SpdyFramer framer(spdy_version_);
3989 scoped_ptr<SpdyFrame> control_frame(
3990 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3991 TestSpdyVisitor visitor(spdy_version_);
3992 visitor.SimulateInFramer(
3993 reinterpret_cast<unsigned char*>(control_frame->data()),
3994 control_frame->size());
3995 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3996 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3999 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4000 if (!IsSpdy3()) {
4001 return;
4003 SpdyFramer framer(spdy_version_);
4004 const unsigned char kV3FrameData[] = { // Also applies for V2.
4005 0x80, spdy_version_ch_, 0x00, 0x0A,
4006 0x00, 0x00, 0x00, 0x33,
4007 0x00, 0x03, 0x00, 0x00,
4008 0x00, 0x05, 'p', 'r',
4009 'o', 'o', 'f', 0x00,
4010 0x00, 0x00, 0x06, 'a',
4011 ' ', 'c', 'e', 'r',
4012 't', 0x00, 0x00, 0x00,
4013 0x0C, 'a', 'n', 'o',
4014 't', 'h', 'e', 'r',
4015 ' ', 'c', 'e', 'r',
4016 't', 0x00, 0x00, 0x00,
4017 0x0A, 'f', 'i', 'n',
4018 'a', 'l', ' ', 'c',
4019 'e', 'r', 't',
4021 TestSpdyVisitor visitor(spdy_version_);
4022 visitor.use_compression_ = false;
4023 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4024 EXPECT_EQ(0, visitor.error_count_);
4027 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4028 if (!IsSpdy3()) {
4029 return;
4031 SpdyFramer framer(spdy_version_);
4032 const unsigned char kV3FrameData[] = { // Also applies for V2.
4033 0x80, spdy_version_ch_, 0x00, 0x0A,
4034 0x00, 0x00, 0x00, 0x33,
4035 0x00, 0x03, 0x00, 0x00,
4036 0x00, 0x05, 'p', 'r',
4037 'o', 'o', 'f', 0x00,
4038 0x00, 0x00, 0x06, 'a',
4039 ' ', 'c', 'e', 'r',
4040 't', 0x00, 0x00, 0x00,
4041 0x0C, 'a', 'n', 'o',
4042 't', 'h', 'e', 'r',
4043 ' ', 'c', 'e', 'r',
4044 't', 0x00, 0x00, 0x00,
4045 0x0A, 'f', 'i', 'n',
4046 'a', 'l', ' ', 'c',
4047 'e', 'r', 't',
4049 TestSpdyVisitor visitor(spdy_version_);
4050 visitor.use_compression_ = false;
4051 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4052 arraysize(kV3FrameData));
4053 scoped_ptr<SpdyFrame> control_frame(
4054 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4055 multiple_frame_data.append(string(control_frame->data(),
4056 control_frame->size()));
4057 visitor.SimulateInFramer(
4058 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4059 multiple_frame_data.length());
4060 EXPECT_EQ(0, visitor.error_count_);
4061 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4062 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4065 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4066 if (spdy_version_ <= SPDY3) {
4067 return;
4070 SpdyFramer framer(spdy_version_);
4071 SpdyPushPromiseIR push_promise(42, 57);
4072 push_promise.SetHeader("foo", "bar");
4073 push_promise.SetHeader("bar", "foofoo");
4074 SpdyHeaderBlock headers = push_promise.name_value_block();
4075 scoped_ptr<SpdySerializedFrame> frame(
4076 framer.SerializePushPromise(push_promise));
4077 EXPECT_TRUE(frame.get() != NULL);
4078 TestSpdyVisitor visitor(spdy_version_);
4079 visitor.use_compression_ = true;
4080 visitor.SimulateInFramer(
4081 reinterpret_cast<unsigned char*>(frame->data()),
4082 frame->size());
4083 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4084 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4085 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4088 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4089 if (spdy_version_ <= SPDY3) {
4090 return;
4093 const unsigned char kInput[] = {
4094 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4095 0x00, 0x00, 0x00, 0x01, // Stream 1
4096 0x03, // Padding of 3.
4097 0x00, 0x06, 0x63, 0x6f,
4098 0x6f, 0x6b, 0x69, 0x65,
4099 0x07, 0x66, 0x6f, 0x6f,
4100 0x3d, 0x62, 0x61, 0x72,
4101 0x00, 0x00, 0x00,
4103 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4104 0x00, 0x00, 0x00, 0x01, // Stream 1
4105 0x00, 0x06, 0x63, 0x6f,
4106 0x6f, 0x6b, 0x69, 0x65,
4107 0x08, 0x62, 0x61, 0x7a,
4108 0x3d, 0x62, 0x69, 0x6e,
4109 0x67, 0x00, 0x06, 0x63,
4111 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4112 0x00, 0x00, 0x00, 0x01, // Stream 1
4113 0x6f, 0x6f, 0x6b, 0x69,
4114 0x65, 0x00, 0x00, 0x04,
4115 0x6e, 0x61, 0x6d, 0x65,
4116 0x05, 0x76, 0x61, 0x6c,
4117 0x75, 0x65,
4120 TestSpdyVisitor visitor(spdy_version_);
4121 visitor.SimulateInFramer(kInput, sizeof(kInput));
4123 EXPECT_EQ(0, visitor.error_count_);
4124 EXPECT_EQ(1, visitor.headers_frame_count_);
4125 EXPECT_EQ(2, visitor.continuation_count_);
4126 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4127 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4129 EXPECT_THAT(visitor.headers_, ElementsAre(
4130 Pair("cookie", "foo=bar; baz=bing; "),
4131 Pair("name", "value")));
4134 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4135 if (spdy_version_ <= SPDY3) {
4136 return;
4139 const unsigned char kInput[] = {
4140 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4141 0x00, 0x00, 0x00, 0x01, // Stream 1
4142 0x00, 0x06, 0x63, 0x6f,
4143 0x6f, 0x6b, 0x69, 0x65,
4144 0x07, 0x66, 0x6f, 0x6f,
4145 0x3d, 0x62, 0x61, 0x72,
4147 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4148 0x00, 0x00, 0x00, 0x01, // Stream 1
4149 0x00, 0x06, 0x63, 0x6f,
4150 0x6f, 0x6b, 0x69, 0x65,
4151 0x08, 0x62, 0x61, 0x7a,
4152 0x3d, 0x62, 0x69, 0x6e,
4153 0x67, 0x00, 0x06, 0x63,
4155 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4156 0x00, 0x00, 0x00, 0x01, // Stream 1
4157 0x6f, 0x6f, 0x6b, 0x69,
4158 0x65, 0x00, 0x00, 0x04,
4159 0x6e, 0x61, 0x6d, 0x65,
4160 0x05, 0x76, 0x61, 0x6c,
4161 0x75, 0x65,
4164 SpdyFramer framer(spdy_version_);
4165 TestSpdyVisitor visitor(spdy_version_);
4166 visitor.SimulateInFramer(kInput, sizeof(kInput));
4168 EXPECT_EQ(0, visitor.error_count_);
4169 EXPECT_EQ(1, visitor.headers_frame_count_);
4170 EXPECT_EQ(2, visitor.continuation_count_);
4171 EXPECT_EQ(1, visitor.fin_flag_count_);
4172 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4173 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4175 EXPECT_THAT(visitor.headers_, ElementsAre(
4176 Pair("cookie", "foo=bar; baz=bing; "),
4177 Pair("name", "value")));
4180 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4181 if (spdy_version_ <= SPDY3) {
4182 return;
4185 const unsigned char kInput[] = {
4186 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4187 0x08, 0x00, 0x00, 0x00, // PADDED
4188 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4189 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4190 0x63, 0x6f, 0x6f, 0x6b,
4191 0x69, 0x65, 0x07, 0x66,
4192 0x6f, 0x6f, 0x3d, 0x62,
4193 0x61, 0x72, 0x00, 0x00,
4195 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4196 0x00, 0x00, 0x00, 0x00,
4197 0x01, 0x00, 0x06, 0x63, // Stream 1
4198 0x6f, 0x6f, 0x6b, 0x69,
4199 0x65, 0x08, 0x62, 0x61,
4200 0x7a, 0x3d, 0x62, 0x69,
4201 0x6e, 0x67, 0x00, 0x06,
4202 0x63,
4204 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4205 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4206 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4207 0x69, 0x65, 0x00, 0x00,
4208 0x04, 0x6e, 0x61, 0x6d,
4209 0x65, 0x05, 0x76, 0x61,
4210 0x6c, 0x75, 0x65,
4213 SpdyFramer framer(spdy_version_);
4214 TestSpdyVisitor visitor(spdy_version_);
4215 visitor.SimulateInFramer(kInput, sizeof(kInput));
4217 EXPECT_EQ(0, visitor.error_count_);
4218 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4219 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4220 EXPECT_EQ(2, visitor.continuation_count_);
4221 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4222 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4224 EXPECT_THAT(visitor.headers_, ElementsAre(
4225 Pair("cookie", "foo=bar; baz=bing; "),
4226 Pair("name", "value")));
4229 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4230 if (spdy_version_ <= SPDY3) {
4231 return;
4234 const unsigned char kInput[] = {
4235 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4236 0x00, 0x00, 0x00, 0x01, // Stream 1
4237 0x00, 0x06, 0x63, 0x6f,
4238 0x6f, 0x6b, 0x69, 0x65,
4239 0x07, 0x66, 0x6f, 0x6f,
4240 0x3d, 0x62, 0x61, 0x72,
4242 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4243 0x00, 0x00, 0x00, 0x02, // Stream 2
4244 0x00, 0x06, 0x63, 0x6f,
4245 0x6f, 0x6b, 0x69, 0x65,
4246 0x08, 0x62, 0x61, 0x7a,
4247 0x3d, 0x62, 0x69, 0x6e,
4248 0x67, 0x00, 0x06, 0x63,
4251 SpdyFramer framer(spdy_version_);
4252 TestSpdyVisitor visitor(spdy_version_);
4253 framer.set_visitor(&visitor);
4254 visitor.SimulateInFramer(kInput, sizeof(kInput));
4256 EXPECT_EQ(1, visitor.error_count_);
4257 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4258 visitor.framer_.error_code())
4259 << SpdyFramer::ErrorCodeToString(framer.error_code());
4260 EXPECT_EQ(1, visitor.headers_frame_count_);
4261 EXPECT_EQ(0, visitor.continuation_count_);
4262 EXPECT_EQ(0u, visitor.header_buffer_length_);
4265 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4266 if (spdy_version_ <= SPDY3) {
4267 return;
4270 const unsigned char kInput[] = {
4271 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4272 0x00, 0x00, 0x00, 0x01, // Stream 1
4273 0x00, 0x06, 0x63, 0x6f,
4274 0x6f, 0x6b, 0x69, 0x65,
4275 0x07, 0x66, 0x6f, 0x6f,
4276 0x3d, 0x62, 0x61, 0x72,
4279 SpdyFramer framer(spdy_version_);
4280 TestSpdyVisitor visitor(spdy_version_);
4281 framer.set_visitor(&visitor);
4282 visitor.SimulateInFramer(kInput, sizeof(kInput));
4284 EXPECT_EQ(1, visitor.error_count_);
4285 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4286 visitor.framer_.error_code())
4287 << SpdyFramer::ErrorCodeToString(framer.error_code());
4288 EXPECT_EQ(0, visitor.continuation_count_);
4289 EXPECT_EQ(0u, visitor.header_buffer_length_);
4292 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4293 if (spdy_version_ <= SPDY3) {
4294 return;
4297 const unsigned char kInput[] = {
4298 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4299 0x00, 0x00, 0x00, 0x01, // Stream 1
4300 0x00, 0x06, 0x63, 0x6f,
4301 0x6f, 0x6b, 0x69, 0x65,
4302 0x07, 0x66, 0x6f, 0x6f,
4303 0x3d, 0x62, 0x61, 0x72,
4305 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4306 0x00, 0x00, 0x00, 0x04,
4307 0xde, 0xad, 0xbe, 0xef,
4310 SpdyFramer framer(spdy_version_);
4311 TestSpdyVisitor visitor(spdy_version_);
4312 framer.set_visitor(&visitor);
4313 visitor.SimulateInFramer(kInput, sizeof(kInput));
4315 EXPECT_EQ(1, visitor.error_count_);
4316 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4317 visitor.framer_.error_code())
4318 << SpdyFramer::ErrorCodeToString(framer.error_code());
4319 EXPECT_EQ(1, visitor.headers_frame_count_);
4320 EXPECT_EQ(0, visitor.continuation_count_);
4321 EXPECT_EQ(0u, visitor.header_buffer_length_);
4322 EXPECT_EQ(0, visitor.data_frame_count_);
4325 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4326 if (spdy_version_ <= SPDY3) {
4327 return;
4330 const unsigned char kInput[] = {
4331 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4332 0x00, 0x00, 0x00, 0x01, // Stream 1
4333 0x00, 0x06, 0x63, 0x6f,
4334 0x6f, 0x6b, 0x69, 0x65,
4335 0x07, 0x66, 0x6f, 0x6f,
4336 0x3d, 0x62, 0x61, 0x72,
4338 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4339 0x00, 0x00, 0x00, 0x01, // Stream 1
4340 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4341 0x6f, 0x6b, 0x69, 0x65,
4342 0x08, 0x62, 0x61, 0x7a,
4343 0x3d, 0x62, 0x69, 0x6e,
4344 0x67, 0x00, 0x06, 0x63,
4347 SpdyFramer framer(spdy_version_);
4348 TestSpdyVisitor visitor(spdy_version_);
4349 framer.set_visitor(&visitor);
4350 visitor.SimulateInFramer(kInput, sizeof(kInput));
4352 EXPECT_EQ(1, visitor.error_count_);
4353 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4354 visitor.framer_.error_code())
4355 << SpdyFramer::ErrorCodeToString(framer.error_code());
4356 EXPECT_EQ(1, visitor.headers_frame_count_);
4357 EXPECT_EQ(0, visitor.continuation_count_);
4358 EXPECT_EQ(0u, visitor.header_buffer_length_);
4359 EXPECT_EQ(0, visitor.data_frame_count_);
4362 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4363 if (spdy_version_ <= SPDY3) {
4364 return;
4366 const unsigned char kInput[] = {
4367 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4368 0x00, 0x00, 0x00, 0x01, // Stream 1
4369 0xde, 0xad, 0xbe, 0xef,
4370 0xde, 0xad, 0xbe, 0xef,
4371 0xde, 0xad, 0xbe, 0xef,
4374 TestSpdyVisitor visitor(spdy_version_);
4375 visitor.SimulateInFramer(kInput, sizeof(kInput));
4377 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4378 EXPECT_EQ(0, visitor.error_count_);
4379 EXPECT_EQ(12, visitor.data_bytes_);
4380 EXPECT_EQ(0, visitor.fin_frame_count_);
4381 EXPECT_EQ(0, visitor.fin_flag_count_);
4384 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4385 if (spdy_version_ <= SPDY3) {
4386 return;
4388 const unsigned char kInput[] = {
4389 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4390 0x00, 0x00, 0x00, 0x01, // Stream 1
4391 0x00, 0x06, 0x63, 0x6f,
4392 0x6f, 0x6b, 0x69, 0x65,
4393 0x07, 0x66, 0x6f, 0x6f,
4394 0x3d, 0x62, 0x61, 0x72,
4397 TestSpdyVisitor visitor(spdy_version_);
4398 visitor.SimulateInFramer(kInput, sizeof(kInput));
4400 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4401 EXPECT_EQ(0, visitor.error_count_);
4402 EXPECT_EQ(1, visitor.headers_frame_count_);
4403 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4405 EXPECT_THAT(visitor.headers_, ElementsAre(
4406 Pair("cookie", "foo=bar")));
4409 TEST_P(SpdyFramerTest, ReadGarbage) {
4410 SpdyFramer framer(spdy_version_);
4411 unsigned char garbage_frame[256];
4412 memset(garbage_frame, ~0, sizeof(garbage_frame));
4413 TestSpdyVisitor visitor(spdy_version_);
4414 visitor.use_compression_ = false;
4415 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4416 EXPECT_EQ(1, visitor.error_count_);
4419 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4420 if (spdy_version_ <= SPDY3) {
4421 return;
4423 SpdyFramer framer(spdy_version_);
4425 // The unrecognized frame type should still have a valid length.
4426 const unsigned char unknown_frame[] = {
4427 0x00, 0x00, 0x08, 0xff, 0xff,
4428 0xff, 0xff, 0xff, 0xff,
4429 0xff, 0xff, 0xff, 0xff,
4430 0xff, 0xff, 0xff, 0xff,
4432 TestSpdyVisitor visitor(spdy_version_);
4434 // Simulate the case where the stream id validation checks out.
4435 visitor.on_unknown_frame_result_ = true;
4436 visitor.use_compression_ = false;
4437 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4438 EXPECT_EQ(0, visitor.error_count_);
4440 // Follow it up with a valid control frame to make sure we handle
4441 // subsequent frames correctly.
4442 SpdySettingsIR settings_ir;
4443 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4444 false, // persist
4445 false, // persisted
4446 10);
4447 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4448 visitor.SimulateInFramer(
4449 reinterpret_cast<unsigned char*>(control_frame->data()),
4450 control_frame->size());
4451 EXPECT_EQ(0, visitor.error_count_);
4452 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4453 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4456 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4457 if (!IsSpdy4()) {
4458 return;
4460 SpdyFramer framer(spdy_version_);
4461 const unsigned char kFrameData[] = {
4462 0x00, 0x00, 0x08, 0xff, 0xff,
4463 0xff, 0xff, 0xff, 0xff,
4464 0xff, 0xff, 0xff, 0xff,
4465 0xff, 0xff, 0xff, 0xff,
4467 TestSpdyVisitor visitor(spdy_version_);
4468 visitor.use_compression_ = false;
4469 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4470 EXPECT_EQ(1, visitor.error_count_);
4473 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4474 if (IsSpdy4()) {
4475 // Not valid for SPDY 4 since there is no version field.
4476 return;
4478 SpdyFramer framer(spdy_version_);
4479 const unsigned char kFrameData[] = {
4480 0x80, spdy_version_ch_, 0xff, 0xff,
4481 0xff, 0xff, 0xff, 0xff,
4483 TestSpdyVisitor visitor(spdy_version_);
4484 visitor.use_compression_ = false;
4485 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4486 EXPECT_EQ(1, visitor.error_count_);
4489 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4490 if (spdy_version_ <= SPDY3) {
4491 return;
4493 const unsigned char kInput[] = {
4494 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4495 0x00, 0x00, 0x00, 0x01, // Stream 1
4496 0xef, 0xef, 0xff, 0xff,
4497 0xff, 0xff, 0xff, 0xff,
4498 0xff, 0xff, 0xff, 0xff,
4499 0xff, 0xff, 0xff, 0xff,
4500 0xff, 0xff,
4503 TestSpdyVisitor visitor(spdy_version_);
4504 visitor.SimulateInFramer(kInput, arraysize(kInput));
4505 EXPECT_EQ(1, visitor.error_count_);
4508 TEST_P(SpdyFramerTest, SizesTest) {
4509 SpdyFramer framer(spdy_version_);
4510 if (IsSpdy4() || IsSpdy5()) {
4511 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4512 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4513 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4514 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4515 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4516 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4517 EXPECT_EQ(17u, framer.GetPingSize());
4518 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4519 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4520 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4521 EXPECT_EQ(9u, framer.GetBlockedSize());
4522 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4523 EXPECT_EQ(18u, framer.GetAltSvcMinimumSize());
4524 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4525 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4526 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4527 } else {
4528 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4529 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4530 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4531 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4532 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4533 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4534 EXPECT_EQ(12u, framer.GetPingSize());
4535 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4536 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4537 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4538 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4539 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4540 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4544 TEST_P(SpdyFramerTest, StateToStringTest) {
4545 EXPECT_STREQ("ERROR",
4546 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4547 EXPECT_STREQ("AUTO_RESET",
4548 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4549 EXPECT_STREQ("RESET",
4550 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4551 EXPECT_STREQ("READING_COMMON_HEADER",
4552 SpdyFramer::StateToString(
4553 SpdyFramer::SPDY_READING_COMMON_HEADER));
4554 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4555 SpdyFramer::StateToString(
4556 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4557 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4558 SpdyFramer::StateToString(
4559 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4560 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4561 SpdyFramer::StateToString(
4562 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4563 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4564 SpdyFramer::StateToString(
4565 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4566 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4567 SpdyFramer::StateToString(
4568 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4569 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4570 SpdyFramer::StateToString(
4571 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4572 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4573 SpdyFramer::StateToString(
4574 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4575 EXPECT_STREQ("UNKNOWN_STATE",
4576 SpdyFramer::StateToString(
4577 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4580 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4581 EXPECT_STREQ("NO_ERROR",
4582 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4583 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4584 SpdyFramer::ErrorCodeToString(
4585 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4586 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4587 SpdyFramer::ErrorCodeToString(
4588 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4589 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4590 SpdyFramer::ErrorCodeToString(
4591 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4592 EXPECT_STREQ("UNSUPPORTED_VERSION",
4593 SpdyFramer::ErrorCodeToString(
4594 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4595 EXPECT_STREQ("DECOMPRESS_FAILURE",
4596 SpdyFramer::ErrorCodeToString(
4597 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4598 EXPECT_STREQ("COMPRESS_FAILURE",
4599 SpdyFramer::ErrorCodeToString(
4600 SpdyFramer::SPDY_COMPRESS_FAILURE));
4601 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4602 SpdyFramer::ErrorCodeToString(
4603 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4604 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4605 SpdyFramer::ErrorCodeToString(
4606 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4607 EXPECT_STREQ("UNKNOWN_ERROR",
4608 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4611 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4612 EXPECT_STREQ("INVALID",
4613 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4614 EXPECT_STREQ("PROTOCOL_ERROR",
4615 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4616 EXPECT_STREQ("INVALID_STREAM",
4617 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4618 EXPECT_STREQ("REFUSED_STREAM",
4619 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4620 EXPECT_STREQ("UNSUPPORTED_VERSION",
4621 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4622 EXPECT_STREQ("CANCEL",
4623 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4624 EXPECT_STREQ("INTERNAL_ERROR",
4625 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4626 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4627 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4628 EXPECT_STREQ("UNKNOWN_STATUS",
4629 SpdyFramer::StatusCodeToString(-1));
4632 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4633 EXPECT_STREQ("DATA",
4634 SpdyFramer::FrameTypeToString(DATA));
4635 EXPECT_STREQ("SYN_STREAM",
4636 SpdyFramer::FrameTypeToString(SYN_STREAM));
4637 EXPECT_STREQ("SYN_REPLY",
4638 SpdyFramer::FrameTypeToString(SYN_REPLY));
4639 EXPECT_STREQ("RST_STREAM",
4640 SpdyFramer::FrameTypeToString(RST_STREAM));
4641 EXPECT_STREQ("SETTINGS",
4642 SpdyFramer::FrameTypeToString(SETTINGS));
4643 EXPECT_STREQ("PING",
4644 SpdyFramer::FrameTypeToString(PING));
4645 EXPECT_STREQ("GOAWAY",
4646 SpdyFramer::FrameTypeToString(GOAWAY));
4647 EXPECT_STREQ("HEADERS",
4648 SpdyFramer::FrameTypeToString(HEADERS));
4649 EXPECT_STREQ("WINDOW_UPDATE",
4650 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4651 EXPECT_STREQ("PUSH_PROMISE",
4652 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4653 EXPECT_STREQ("CREDENTIAL",
4654 SpdyFramer::FrameTypeToString(CREDENTIAL));
4655 EXPECT_STREQ("CONTINUATION",
4656 SpdyFramer::FrameTypeToString(CONTINUATION));
4659 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4660 if (IsSpdy4()) {
4661 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4662 return;
4665 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4666 SpdyFramer framer(spdy_version_);
4667 framer.set_visitor(&visitor);
4669 EXPECT_CALL(visitor, OnError(_));
4670 framer.ProcessInput("HTTP/1.1", 8);
4671 EXPECT_TRUE(framer.probable_http_response());
4672 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4673 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4674 << SpdyFramer::ErrorCodeToString(framer.error_code());
4677 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4678 SpdyFramer framer(spdy_version_);
4679 framer.set_visitor(&visitor);
4681 EXPECT_CALL(visitor, OnError(_));
4682 framer.ProcessInput("HTTP/1.0", 8);
4683 EXPECT_TRUE(framer.probable_http_response());
4684 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4685 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4686 << SpdyFramer::ErrorCodeToString(framer.error_code());
4690 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4691 if (spdy_version_ > SPDY3) {
4692 return;
4695 for (int flags = 0; flags < 256; ++flags) {
4696 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4698 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4699 SpdyFramer framer(spdy_version_);
4700 framer.set_visitor(&visitor);
4702 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4703 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4704 SetFrameFlags(frame.get(), flags, spdy_version_);
4706 if (flags & ~DATA_FLAG_FIN) {
4707 EXPECT_CALL(visitor, OnError(_));
4708 } else {
4709 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4710 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4711 if (flags & DATA_FLAG_FIN) {
4712 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4716 framer.ProcessInput(frame->data(), frame->size());
4717 if (flags & ~DATA_FLAG_FIN) {
4718 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4719 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4720 framer.error_code())
4721 << SpdyFramer::ErrorCodeToString(framer.error_code());
4722 } else {
4723 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4724 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4725 << SpdyFramer::ErrorCodeToString(framer.error_code());
4730 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4731 if (spdy_version_ <= SPDY3) {
4732 return;
4735 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4736 DATA_FLAG_PADDED;
4738 for (int flags = 0; flags < 256; ++flags) {
4739 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4741 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4742 SpdyFramer framer(spdy_version_);
4743 framer.set_visitor(&visitor);
4745 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4746 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4747 SetFrameFlags(frame.get(), flags, spdy_version_);
4749 if (flags & ~valid_data_flags) {
4750 EXPECT_CALL(visitor, OnError(_));
4751 } else {
4752 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4753 if (flags & DATA_FLAG_PADDED) {
4754 // Expect Error since we don't set padded in payload.
4755 EXPECT_CALL(visitor, OnError(_));
4756 } else {
4757 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4758 if (flags & DATA_FLAG_FIN) {
4759 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4764 framer.ProcessInput(frame->data(), frame->size());
4765 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
4766 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4767 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4768 framer.error_code())
4769 << SpdyFramer::ErrorCodeToString(framer.error_code());
4770 } else {
4771 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4772 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4773 << SpdyFramer::ErrorCodeToString(framer.error_code());
4778 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4779 if (!IsSpdy2() && !IsSpdy3()) {
4780 // SYN_STREAM not supported in SPDY>3
4781 return;
4783 for (int flags = 0; flags < 256; ++flags) {
4784 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4786 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4787 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4788 SpdyFramer framer(spdy_version_);
4789 framer.set_visitor(&visitor);
4790 framer.set_debug_visitor(&debug_visitor);
4792 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4794 SpdySynStreamIR syn_stream(8);
4795 syn_stream.set_associated_to_stream_id(3);
4796 syn_stream.set_priority(1);
4797 syn_stream.SetHeader("foo", "bar");
4798 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4799 int set_flags = flags;
4800 SetFrameFlags(frame.get(), set_flags, spdy_version_);
4802 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4803 EXPECT_CALL(visitor, OnError(_));
4804 } else {
4805 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
4806 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
4807 flags & CONTROL_FLAG_UNIDIRECTIONAL));
4808 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
4809 .WillRepeatedly(testing::Return(true));
4810 if (flags & DATA_FLAG_FIN) {
4811 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4812 } else {
4813 // Do not close the stream if we are expecting a CONTINUATION frame.
4814 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4818 framer.ProcessInput(frame->data(), frame->size());
4819 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4820 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4821 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4822 framer.error_code())
4823 << SpdyFramer::ErrorCodeToString(framer.error_code());
4824 } else {
4825 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4826 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4827 << SpdyFramer::ErrorCodeToString(framer.error_code());
4832 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
4833 if (!IsSpdy2() && !IsSpdy3()) {
4834 // SYN_REPLY not supported in SPDY>3
4835 return;
4837 for (int flags = 0; flags < 256; ++flags) {
4838 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4840 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4841 SpdyFramer framer(spdy_version_);
4842 framer.set_visitor(&visitor);
4844 SpdySynReplyIR syn_reply(37);
4845 syn_reply.SetHeader("foo", "bar");
4846 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
4847 SetFrameFlags(frame.get(), flags, spdy_version_);
4849 if (flags & ~CONTROL_FLAG_FIN) {
4850 EXPECT_CALL(visitor, OnError(_));
4851 } else {
4852 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
4853 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
4854 .WillRepeatedly(testing::Return(true));
4855 if (flags & DATA_FLAG_FIN) {
4856 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4860 framer.ProcessInput(frame->data(), frame->size());
4861 if (flags & ~CONTROL_FLAG_FIN) {
4862 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4863 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4864 framer.error_code())
4865 << SpdyFramer::ErrorCodeToString(framer.error_code());
4866 } else {
4867 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4868 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4869 << SpdyFramer::ErrorCodeToString(framer.error_code());
4874 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
4875 for (int flags = 0; flags < 256; ++flags) {
4876 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4878 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4879 SpdyFramer framer(spdy_version_);
4880 framer.set_visitor(&visitor);
4882 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
4883 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
4884 SetFrameFlags(frame.get(), flags, spdy_version_);
4886 if (flags != 0) {
4887 EXPECT_CALL(visitor, OnError(_));
4888 } else {
4889 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
4892 framer.ProcessInput(frame->data(), frame->size());
4893 if (flags != 0) {
4894 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4895 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4896 framer.error_code())
4897 << SpdyFramer::ErrorCodeToString(framer.error_code());
4898 } else {
4899 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4900 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4901 << SpdyFramer::ErrorCodeToString(framer.error_code());
4906 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
4907 if (spdy_version_ > SPDY3) { return; }
4908 for (int flags = 0; flags < 256; ++flags) {
4909 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4911 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4912 SpdyFramer framer(spdy_version_);
4913 framer.set_visitor(&visitor);
4915 SpdySettingsIR settings_ir;
4916 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
4917 false,
4918 false,
4919 54321);
4920 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
4921 SetFrameFlags(frame.get(), flags, spdy_version_);
4923 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
4924 EXPECT_CALL(visitor, OnError(_));
4925 } else {
4926 EXPECT_CALL(visitor, OnSettings(
4927 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
4928 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
4929 SETTINGS_FLAG_NONE, 54321));
4930 EXPECT_CALL(visitor, OnSettingsEnd());
4933 framer.ProcessInput(frame->data(), frame->size());
4934 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
4935 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4936 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4937 framer.error_code())
4938 << SpdyFramer::ErrorCodeToString(framer.error_code());
4939 } else {
4940 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4941 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4942 << SpdyFramer::ErrorCodeToString(framer.error_code());
4947 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
4948 if (spdy_version_ <= SPDY3) { return; }
4949 for (int flags = 0; flags < 256; ++flags) {
4950 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4952 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4953 SpdyFramer framer(spdy_version_);
4954 framer.set_visitor(&visitor);
4956 SpdySettingsIR settings_ir;
4957 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
4958 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
4959 SetFrameFlags(frame.get(), flags, spdy_version_);
4961 if (flags != 0) {
4962 EXPECT_CALL(visitor, OnError(_));
4963 } else {
4964 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
4965 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
4966 EXPECT_CALL(visitor, OnSettingsEnd());
4969 framer.ProcessInput(frame->data(), frame->size());
4970 if (flags & ~SETTINGS_FLAG_ACK) {
4971 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4972 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4973 framer.error_code())
4974 << SpdyFramer::ErrorCodeToString(framer.error_code());
4975 } else if (flags & SETTINGS_FLAG_ACK) {
4976 // The frame is invalid because ACK frames should have no payload.
4977 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4978 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4979 framer.error_code())
4980 << SpdyFramer::ErrorCodeToString(framer.error_code());
4981 } else {
4982 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4983 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4984 << SpdyFramer::ErrorCodeToString(framer.error_code());
4989 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
4990 for (int flags = 0; flags < 256; ++flags) {
4991 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4993 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4994 SpdyFramer framer(spdy_version_);
4995 framer.set_visitor(&visitor);
4997 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
4998 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
4999 SetFrameFlags(frame.get(), flags, spdy_version_);
5001 if (flags != 0) {
5002 EXPECT_CALL(visitor, OnError(_));
5003 } else {
5004 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5007 framer.ProcessInput(frame->data(), frame->size());
5008 if (flags != 0) {
5009 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5010 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5011 framer.error_code())
5012 << SpdyFramer::ErrorCodeToString(framer.error_code());
5013 } else {
5014 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5015 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5016 << SpdyFramer::ErrorCodeToString(framer.error_code());
5021 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5022 for (int flags = 0; flags < 256; ++flags) {
5023 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5025 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5026 SpdyFramer framer(spdy_version_);
5027 framer.set_visitor(&visitor);
5029 SpdyHeadersIR headers_ir(57);
5030 if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
5031 headers_ir.set_priority(3);
5032 headers_ir.set_has_priority(true);
5034 headers_ir.SetHeader("foo", "bar");
5035 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5036 int set_flags = flags;
5037 if (IsSpdy4()) {
5038 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5039 // and implement framing.
5040 set_flags &= ~HEADERS_FLAG_PADDED;
5042 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5044 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5045 EXPECT_CALL(visitor, OnError(_));
5046 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5047 HEADERS_FLAG_END_HEADERS |
5048 HEADERS_FLAG_END_SEGMENT |
5049 HEADERS_FLAG_PADDED |
5050 HEADERS_FLAG_PRIORITY)) {
5051 EXPECT_CALL(visitor, OnError(_));
5052 } else {
5053 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5054 EXPECT_CALL(visitor, OnSynStream(57, // stream id
5055 0, // associated stream id
5056 3, // priority
5057 flags & CONTROL_FLAG_FIN,
5058 false)); // unidirectional
5059 } else {
5060 EXPECT_CALL(visitor, OnHeaders(57,
5061 flags & CONTROL_FLAG_FIN,
5062 (flags & HEADERS_FLAG_END_HEADERS) ||
5063 !IsSpdy4()));
5065 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5066 .WillRepeatedly(testing::Return(true));
5067 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
5068 flags & HEADERS_FLAG_END_HEADERS)) {
5069 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5070 } else {
5071 // Do not close the stream if we are expecting a CONTINUATION frame.
5072 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5076 framer.ProcessInput(frame->data(), frame->size());
5077 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5078 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5079 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5080 framer.error_code())
5081 << SpdyFramer::ErrorCodeToString(framer.error_code());
5082 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5083 HEADERS_FLAG_END_HEADERS |
5084 HEADERS_FLAG_END_SEGMENT |
5085 HEADERS_FLAG_PADDED |
5086 HEADERS_FLAG_PRIORITY)) {
5087 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5088 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5089 framer.error_code())
5090 << SpdyFramer::ErrorCodeToString(framer.error_code());
5091 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5092 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5093 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5094 << SpdyFramer::ErrorCodeToString(framer.error_code());
5095 } else {
5096 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5097 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5098 << SpdyFramer::ErrorCodeToString(framer.error_code());
5103 TEST_P(SpdyFramerTest, PingFrameFlags) {
5104 for (int flags = 0; flags < 256; ++flags) {
5105 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5107 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5108 SpdyFramer framer(spdy_version_);
5109 framer.set_visitor(&visitor);
5111 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5112 SetFrameFlags(frame.get(), flags, spdy_version_);
5114 if (spdy_version_ > SPDY3 &&
5115 flags == PING_FLAG_ACK) {
5116 EXPECT_CALL(visitor, OnPing(42, true));
5117 } else if (flags == 0) {
5118 EXPECT_CALL(visitor, OnPing(42, false));
5119 } else {
5120 EXPECT_CALL(visitor, OnError(_));
5123 framer.ProcessInput(frame->data(), frame->size());
5124 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5125 flags == 0) {
5126 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5127 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5128 << SpdyFramer::ErrorCodeToString(framer.error_code());
5129 } else {
5130 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5131 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5132 framer.error_code())
5133 << SpdyFramer::ErrorCodeToString(framer.error_code());
5138 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5139 for (int flags = 0; flags < 256; ++flags) {
5140 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5142 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5143 SpdyFramer framer(spdy_version_);
5144 framer.set_visitor(&visitor);
5146 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5147 SpdyWindowUpdateIR(4, 1024)));
5148 SetFrameFlags(frame.get(), flags, spdy_version_);
5150 if (flags != 0) {
5151 EXPECT_CALL(visitor, OnError(_));
5152 } else {
5153 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5156 framer.ProcessInput(frame->data(), frame->size());
5157 if (flags != 0) {
5158 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5159 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5160 framer.error_code())
5161 << SpdyFramer::ErrorCodeToString(framer.error_code());
5162 } else {
5163 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5164 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5165 << SpdyFramer::ErrorCodeToString(framer.error_code());
5170 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5171 if (spdy_version_ <= SPDY3) {
5172 return;
5175 for (int flags = 0; flags < 256; ++flags) {
5176 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5178 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
5179 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5180 SpdyFramer framer(spdy_version_);
5181 framer.set_visitor(&visitor);
5182 framer.set_debug_visitor(&debug_visitor);
5184 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5186 SpdyPushPromiseIR push_promise(42, 57);
5187 push_promise.SetHeader("foo", "bar");
5188 scoped_ptr<SpdySerializedFrame> frame(
5189 framer.SerializePushPromise(push_promise));
5190 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5191 // and implement framing.
5192 int set_flags = flags & ~HEADERS_FLAG_PADDED;
5193 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5195 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5196 EXPECT_CALL(visitor, OnError(_));
5197 } else {
5198 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5199 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5200 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5201 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5202 .WillRepeatedly(testing::Return(true));
5205 framer.ProcessInput(frame->data(), frame->size());
5206 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5207 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5208 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5209 framer.error_code())
5210 << SpdyFramer::ErrorCodeToString(framer.error_code());
5211 } else {
5212 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5213 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5214 << SpdyFramer::ErrorCodeToString(framer.error_code());
5219 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5220 if (spdy_version_ <= SPDY3) {
5221 return;
5224 for (int flags = 0; flags < 256; ++flags) {
5225 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5227 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5228 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5229 SpdyFramer framer(spdy_version_);
5230 framer.set_visitor(&visitor);
5231 framer.set_debug_visitor(&debug_visitor);
5233 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5234 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5235 EXPECT_CALL(visitor, OnHeaders(42, 0, false));
5236 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5237 .WillRepeatedly(testing::Return(true));
5239 SpdyHeadersIR headers_ir(42);
5240 headers_ir.SetHeader("foo", "bar");
5241 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5242 SetFrameFlags(frame0.get(), 0, spdy_version_);
5244 SpdyContinuationIR continuation(42);
5245 continuation.SetHeader("foo", "bar");
5246 scoped_ptr<SpdySerializedFrame> frame(
5247 framer.SerializeContinuation(continuation));
5248 SetFrameFlags(frame.get(), flags, spdy_version_);
5250 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5251 EXPECT_CALL(visitor, OnError(_));
5252 } else {
5253 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5254 EXPECT_CALL(visitor, OnContinuation(42,
5255 flags & HEADERS_FLAG_END_HEADERS));
5256 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5257 .WillRepeatedly(testing::Return(true));
5260 framer.ProcessInput(frame0->data(), frame0->size());
5261 framer.ProcessInput(frame->data(), frame->size());
5262 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5263 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5264 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5265 framer.error_code())
5266 << SpdyFramer::ErrorCodeToString(framer.error_code());
5267 } else {
5268 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5269 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5270 << SpdyFramer::ErrorCodeToString(framer.error_code());
5275 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5277 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5279 TEST_P(SpdyFramerTest, EmptySynStream) {
5280 if (!IsSpdy2() && !IsSpdy3()) {
5281 // SYN_STREAM not supported in SPDY>3.
5282 return;
5284 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5285 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5286 SpdyFramer framer(spdy_version_);
5287 framer.set_visitor(&visitor);
5288 framer.set_debug_visitor(&debug_visitor);
5290 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5292 SpdySynStreamIR syn_stream(1);
5293 syn_stream.set_priority(1);
5294 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5295 // Adjust size to remove the name/value block.
5296 SetFrameLength(
5297 frame.get(),
5298 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5299 spdy_version_);
5301 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5302 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5303 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5305 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5306 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5307 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5308 << SpdyFramer::ErrorCodeToString(framer.error_code());
5311 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5312 const uint32 kId = 0x020304;
5313 const uint32 kFlags = 0x01;
5314 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5316 SettingsFlagsAndId id_and_flags =
5317 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5318 EXPECT_EQ(kId, id_and_flags.id());
5319 EXPECT_EQ(kFlags, id_and_flags.flags());
5320 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5323 // Test handling of a RST_STREAM with out-of-bounds status codes.
5324 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5325 const unsigned char kRstStreamStatusTooLow = 0x00;
5326 const unsigned char kRstStreamStatusTooHigh = 0xff;
5327 const unsigned char kV3RstStreamInvalid[] = {
5328 0x80, spdy_version_ch_, 0x00, 0x03,
5329 0x00, 0x00, 0x00, 0x08,
5330 0x00, 0x00, 0x00, 0x01,
5331 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5333 const unsigned char kV4RstStreamInvalid[] = {
5334 0x00, 0x00, 0x04, 0x03,
5335 0x00, 0x00, 0x00, 0x00,
5336 0x01, 0x00, 0x00, 0x00,
5337 kRstStreamStatusTooLow
5340 const unsigned char kV3RstStreamNumStatusCodes[] = {
5341 0x80, spdy_version_ch_, 0x00, 0x03,
5342 0x00, 0x00, 0x00, 0x08,
5343 0x00, 0x00, 0x00, 0x01,
5344 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5346 const unsigned char kV4RstStreamNumStatusCodes[] = {
5347 0x00, 0x00, 0x04, 0x03,
5348 0x00, 0x00, 0x00, 0x00,
5349 0x01, 0x00, 0x00, 0x00,
5350 kRstStreamStatusTooHigh
5353 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5354 SpdyFramer framer(spdy_version_);
5355 framer.set_visitor(&visitor);
5357 if (IsSpdy4()) {
5358 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5359 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
5360 arraysize(kV4RstStreamInvalid));
5361 } else {
5362 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5363 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5364 arraysize(kV3RstStreamInvalid));
5366 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5367 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5368 << SpdyFramer::ErrorCodeToString(framer.error_code());
5371 framer.Reset();
5373 if (IsSpdy4()) {
5374 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5375 framer.ProcessInput(
5376 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
5377 arraysize(kV4RstStreamNumStatusCodes));
5378 } else {
5379 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5380 framer.ProcessInput(
5381 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5382 arraysize(kV3RstStreamNumStatusCodes));
5384 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5385 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5386 << SpdyFramer::ErrorCodeToString(framer.error_code());
5389 // Test handling of GOAWAY frames with out-of-bounds status code.
5390 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5391 if (spdy_version_ <= SPDY2) {
5392 return;
5394 SpdyFramer framer(spdy_version_);
5396 const unsigned char kV3FrameData[] = {
5397 0x80, spdy_version_ch_, 0x00, 0x07,
5398 0x00, 0x00, 0x00, 0x08,
5399 0x00, 0x00, 0x00, 0x01, // Stream Id
5400 0xff, 0xff, 0xff, 0xff, // Status
5402 const unsigned char kV4FrameData[] = {
5403 0x00, 0x00, 0x0a, 0x07,
5404 0x00, 0x00, 0x00, 0x00,
5405 0x00, 0x00, 0x00, 0x00, // Stream id
5406 0x01, 0xff, 0xff, 0xff, // Status
5407 0xff, 0x47, 0x41, // Opaque Description
5409 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5410 framer.set_visitor(&visitor);
5412 if (IsSpdy3()) {
5413 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5414 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5415 arraysize(kV3FrameData));
5416 } else {
5417 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5418 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5419 arraysize(kV4FrameData));
5421 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5422 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5423 << SpdyFramer::ErrorCodeToString(framer.error_code());
5426 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5427 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5428 const unsigned char kV2FrameData[] = {
5429 0x80, spdy_version_ch_, 0x00, 0x07,
5430 0x00, 0x00, 0x00, 0x04,
5431 0xff, 0xff, 0xff, 0xff,
5433 const unsigned char kV3FrameData[] = {
5434 0x80, spdy_version_ch_, 0x00, 0x07,
5435 0x00, 0x00, 0x00, 0x08,
5436 0xff, 0xff, 0xff, 0xff,
5437 0x00, 0x00, 0x00, 0x00,
5439 const unsigned char kV4FrameData[] = {
5440 0x00, 0x00, 0x08, 0x07,
5441 0x00, 0x00, 0x00, 0x00,
5442 0x00, 0xff, 0xff, 0xff,
5443 0xff, 0x00, 0x00, 0x00,
5444 0x00,
5447 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5448 SpdyFramer framer(spdy_version_);
5449 framer.set_visitor(&visitor);
5451 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5452 if (IsSpdy2()) {
5453 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5454 arraysize(kV2FrameData));
5455 } else if (IsSpdy3()) {
5456 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5457 arraysize(kV3FrameData));
5458 } else {
5459 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5460 arraysize(kV4FrameData));
5462 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5463 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5464 << SpdyFramer::ErrorCodeToString(framer.error_code());
5467 TEST_P(SpdyFramerTest, OnBlocked) {
5468 if (spdy_version_ <= SPDY3) {
5469 return;
5472 const SpdyStreamId kStreamId = 0;
5474 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5475 SpdyFramer framer(spdy_version_);
5476 framer.set_visitor(&visitor);
5478 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5480 SpdyBlockedIR blocked_ir(0);
5481 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5482 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5484 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5485 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5486 << SpdyFramer::ErrorCodeToString(framer.error_code());
5489 TEST_P(SpdyFramerTest, OnAltSvc) {
5490 if (spdy_version_ <= SPDY3) {
5491 return;
5494 const SpdyStreamId kStreamId = 1;
5496 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5497 SpdyFramer framer(spdy_version_);
5498 framer.set_visitor(&visitor);
5500 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5502 443,
5503 StringPiece("pid"),
5504 StringPiece("h1"),
5505 StringPiece("o1")));
5507 SpdyAltSvcIR altsvc_ir(1);
5508 altsvc_ir.set_max_age(10);
5509 altsvc_ir.set_port(443);
5510 altsvc_ir.set_protocol_id("pid");
5511 altsvc_ir.set_host("h1");
5512 altsvc_ir.set_origin("o1");
5513 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5514 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5515 altsvc_ir.protocol_id().length() +
5516 altsvc_ir.host().length() +
5517 altsvc_ir.origin().length());
5519 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5520 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5521 << SpdyFramer::ErrorCodeToString(framer.error_code());
5524 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5525 if (spdy_version_ <= SPDY3) {
5526 return;
5529 const SpdyStreamId kStreamId = 1;
5531 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5532 SpdyFramer framer(spdy_version_);
5533 framer.set_visitor(&visitor);
5535 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5537 443,
5538 StringPiece("pid"),
5539 StringPiece("h1"),
5540 StringPiece("")));
5542 SpdyAltSvcIR altsvc_ir(1);
5543 altsvc_ir.set_max_age(10);
5544 altsvc_ir.set_port(443);
5545 altsvc_ir.set_protocol_id("pid");
5546 altsvc_ir.set_host("h1");
5547 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5548 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5549 altsvc_ir.protocol_id().length() +
5550 altsvc_ir.host().length());
5552 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5553 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5554 << SpdyFramer::ErrorCodeToString(framer.error_code());
5557 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5558 if (spdy_version_ <= SPDY3) {
5559 return;
5562 const unsigned char kType = static_cast<unsigned char>(
5563 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
5565 TestSpdyVisitor visitor(spdy_version_);
5566 SpdyFramer framer(spdy_version_);
5567 framer.set_visitor(&visitor);
5569 const unsigned char kFrameDataLargePIDLen[] = {
5570 0x00, 0x00, 0x17, kType, 0x00,
5571 0x00, 0x00, 0x00, 0x03,
5572 0x00, 0x00, 0x00, 0x05,
5573 0x01, 0xbb, 0x00, 0x05, // Port = 443
5574 'p', 'i', 'd', '1', // Protocol-ID
5575 0x04, 'h', 'o', 's',
5576 't', 'o', 'r', 'i',
5577 'g', 'i', 'n',
5580 visitor.SimulateInFramer(kFrameDataLargePIDLen,
5581 sizeof(kFrameDataLargePIDLen));
5582 EXPECT_EQ(1, visitor.error_count_);
5583 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5584 visitor.framer_.error_code());
5588 TestSpdyVisitor visitor(spdy_version_);
5589 SpdyFramer framer(spdy_version_);
5590 framer.set_visitor(&visitor);
5591 const unsigned char kFrameDataPIDLenLargerThanFrame[] = {
5592 0x00, 0x00, 0x17, kType, 0x00,
5593 0x00, 0x00, 0x00, 0x03,
5594 0x00, 0x00, 0x00, 0x05,
5595 0x01, 0xbb, 0x00, 0x99, // Port = 443
5596 'p', 'i', 'd', '1', // Protocol-ID
5597 0x04, 'h', 'o', 's',
5598 't', 'o', 'r', 'i',
5599 'g', 'i', 'n',
5602 visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame,
5603 sizeof(kFrameDataPIDLenLargerThanFrame));
5604 EXPECT_EQ(1, visitor.error_count_);
5605 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5606 visitor.framer_.error_code());
5610 TestSpdyVisitor visitor(spdy_version_);
5611 SpdyFramer framer(spdy_version_);
5612 framer.set_visitor(&visitor);
5614 const unsigned char kFrameDataLargeHostLen[] = {
5615 0x00, 0x00, 0x17, kType, 0x00,
5616 0x00, 0x00, 0x00, 0x03,
5617 0x00, 0x00, 0x00, 0x05,
5618 0x01, 0xbb, 0x00, 0x04, // Port = 443
5619 'p', 'i', 'd', '1', // Protocol-ID
5620 0x0f, 'h', 'o', 's',
5621 't', 'o', 'r', 'i',
5622 'g', 'i', 'n',
5625 visitor.SimulateInFramer(kFrameDataLargeHostLen,
5626 sizeof(kFrameDataLargeHostLen));
5627 EXPECT_EQ(1, visitor.error_count_);
5628 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5629 visitor.framer_.error_code());
5633 TestSpdyVisitor visitor(spdy_version_);
5634 SpdyFramer framer(spdy_version_);
5635 framer.set_visitor(&visitor);
5636 const unsigned char kFrameDataSmallPIDLen[] = {
5637 0x00, 0x00, 0x17, kType, 0x00,
5638 0x00, 0x00, 0x00, 0x03,
5639 0x00, 0x00, 0x00, 0x05,
5640 0x01, 0xbb, 0x00, 0x01, // Port = 443
5641 'p', 'i', 'd', '1', // Protocol-ID
5642 0x04, 'h', 'o', 's',
5643 't', 'o', 'r', 'i',
5644 'g', 'i', 'n',
5647 visitor.SimulateInFramer(kFrameDataSmallPIDLen,
5648 sizeof(kFrameDataSmallPIDLen));
5649 EXPECT_EQ(1, visitor.error_count_);
5650 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5651 visitor.framer_.error_code());
5655 // Tests handling of ALTSVC frames delivered in small chunks.
5656 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5657 if (spdy_version_ <= SPDY3) {
5658 return;
5660 SpdyFramer framer(spdy_version_);
5661 SpdyAltSvcIR altsvc_ir(1);
5662 altsvc_ir.set_max_age(20);
5663 altsvc_ir.set_port(443);
5664 altsvc_ir.set_protocol_id("protocolid");
5665 altsvc_ir.set_host("hostname");
5667 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5668 TestSpdyVisitor visitor(spdy_version_);
5669 visitor.use_compression_ = false;
5671 // Read data in small chunks.
5672 size_t framed_data = 0;
5673 size_t unframed_data = control_frame->size();
5674 size_t kReadChunkSize = 5; // Read five bytes at a time.
5675 while (unframed_data > 0) {
5676 size_t to_read = min(kReadChunkSize, unframed_data);
5677 visitor.SimulateInFramer(
5678 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5679 to_read);
5680 unframed_data -= to_read;
5681 framed_data += to_read;
5683 EXPECT_EQ(0, visitor.error_count_);
5684 EXPECT_EQ(1, visitor.altsvc_count_);
5685 EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
5686 EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
5687 EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
5688 EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
5691 // Tests handling of PRIORITY frames.
5692 TEST_P(SpdyFramerTest, ReadPriority) {
5693 if (spdy_version_ <= SPDY3) {
5694 return;
5696 SpdyFramer framer(spdy_version_);
5697 SpdyPriorityIR priority(3, 1, 255, false);
5698 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5699 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5700 framer.set_visitor(&visitor);
5701 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5702 framer.ProcessInput(frame->data(), frame->size());
5704 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5705 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5706 << SpdyFramer::ErrorCodeToString(framer.error_code());
5707 // TODO(mlavan): once we actually maintain a priority tree,
5708 // check that state is adjusted correctly.
5711 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5712 if (spdy_version_ <= SPDY3) {
5713 return;
5715 SpdyFramer framer(spdy_version_);
5717 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5718 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5719 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5720 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5721 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5722 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5723 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5724 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5726 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5727 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5728 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5729 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5730 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5731 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5732 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5733 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5734 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5735 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5736 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5737 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5738 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5739 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5740 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5743 // Tests handling of PRIORITY frame with incorrect size.
5744 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5745 if (spdy_version_ <= SPDY3) {
5746 return;
5749 // PRIORITY frame of size 4, which isn't correct.
5750 const unsigned char kFrameData[] = {
5751 0x00, 0x00, 0x04, 0x02, 0x00,
5752 0x00, 0x00, 0x00, 0x03,
5753 0x00, 0x00, 0x00, 0x01,
5756 TestSpdyVisitor visitor(spdy_version_);
5757 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
5759 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
5760 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5761 visitor.framer_.error_code())
5762 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
5765 } // namespace net