Add FindInPageBridge
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob2676b4df72c65c8234fcf9d18832d191276bea17
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <algorithm>
6 #include <iostream>
7 #include <limits>
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
21 using base::StringPiece;
22 using std::string;
23 using std::max;
24 using std::min;
25 using std::numeric_limits;
26 using testing::ElementsAre;
27 using testing::Pair;
28 using testing::_;
30 namespace net {
32 namespace test {
34 static const size_t kMaxDecompressedSize = 1024;
36 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
37 public:
38 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
39 SpdyFrameType type,
40 size_t payload_len,
41 size_t frame_len));
43 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
44 SpdyFrameType type,
45 size_t frame_len));
48 class SpdyFramerTestUtil {
49 public:
50 // Decompress a single frame using the decompression context held by
51 // the SpdyFramer. The implemention is meant for use only in tests
52 // and will CHECK fail if the input is anything other than a single,
53 // well-formed compressed frame.
55 // Returns a new decompressed SpdyFrame.
56 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
57 SpdyFramer* framer, const SpdyFrameType& frame) {
58 DecompressionVisitor visitor(framer->protocol_version());
59 framer->set_visitor(&visitor);
60 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
61 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
62 framer->set_visitor(NULL);
64 char* buffer = visitor.ReleaseBuffer();
65 CHECK(buffer != NULL);
66 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
67 SetFrameLength(decompressed_frame,
68 visitor.size() - framer->GetControlFrameHeaderSize(),
69 framer->protocol_version());
70 return decompressed_frame;
73 class DecompressionVisitor : public SpdyFramerVisitorInterface {
74 public:
75 explicit DecompressionVisitor(SpdyMajorVersion version)
76 : version_(version), size_(0), finished_(false) {}
78 void ResetBuffer() {
79 CHECK(buffer_.get() == NULL);
80 CHECK_EQ(0u, size_);
81 CHECK(!finished_);
82 buffer_.reset(new char[kMaxDecompressedSize]);
85 virtual void OnError(SpdyFramer* framer) OVERRIDE { LOG(FATAL); }
86 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
87 size_t length,
88 bool fin) OVERRIDE {
89 LOG(FATAL) << "Unexpected data frame header";
91 virtual void OnStreamFrameData(SpdyStreamId stream_id,
92 const char* data,
93 size_t len,
94 bool fin) OVERRIDE {
95 LOG(FATAL);
98 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
99 const char* header_data,
100 size_t len) OVERRIDE {
101 CHECK(buffer_.get() != NULL);
102 CHECK_GE(kMaxDecompressedSize, size_ + len);
103 CHECK(!finished_);
104 if (len != 0) {
105 memcpy(buffer_.get() + size_, header_data, len);
106 size_ += len;
107 } else {
108 // Done.
109 finished_ = true;
111 return true;
114 virtual void OnSynStream(SpdyStreamId stream_id,
115 SpdyStreamId associated_stream_id,
116 SpdyPriority priority,
117 bool fin,
118 bool unidirectional) OVERRIDE {
119 SpdyFramer framer(version_);
120 framer.set_enable_compression(false);
121 SpdySynStreamIR syn_stream(stream_id);
122 syn_stream.set_associated_to_stream_id(associated_stream_id);
123 syn_stream.set_priority(priority);
124 syn_stream.set_fin(fin);
125 syn_stream.set_unidirectional(unidirectional);
126 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
127 ResetBuffer();
128 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
129 size_ += framer.GetSynStreamMinimumSize();
132 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
133 SpdyFramer framer(version_);
134 framer.set_enable_compression(false);
135 SpdyHeadersIR headers(stream_id);
136 headers.set_fin(fin);
137 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
138 ResetBuffer();
139 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
140 size_ += framer.GetSynStreamMinimumSize();
143 virtual void OnRstStream(SpdyStreamId stream_id,
144 SpdyRstStreamStatus status) OVERRIDE {
145 LOG(FATAL);
147 virtual void OnSetting(SpdySettingsIds id,
148 uint8 flags,
149 uint32 value) OVERRIDE {
150 LOG(FATAL);
152 virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
153 LOG(FATAL);
155 virtual void OnSettingsEnd() OVERRIDE { LOG(FATAL); }
156 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
157 SpdyGoAwayStatus status) OVERRIDE {
158 LOG(FATAL);
161 virtual void OnHeaders(SpdyStreamId stream_id,
162 bool fin,
163 bool end) OVERRIDE {
164 SpdyFramer framer(version_);
165 framer.set_enable_compression(false);
166 SpdyHeadersIR headers(stream_id);
167 headers.set_fin(fin);
168 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
169 ResetBuffer();
170 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
171 size_ += framer.GetHeadersMinimumSize();
174 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
175 LOG(FATAL);
178 virtual void OnPushPromise(SpdyStreamId stream_id,
179 SpdyStreamId promised_stream_id,
180 bool end) OVERRIDE {
181 SpdyFramer framer(version_);
182 framer.set_enable_compression(false);
183 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
184 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
185 ResetBuffer();
186 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
187 size_ += framer.GetPushPromiseMinimumSize();
190 virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
191 LOG(FATAL);
194 virtual void OnPriority(SpdyStreamId stream_id,
195 SpdyStreamId parent_stream_id,
196 uint8 weight,
197 bool exclusive) OVERRIDE {
198 // Do nothing.
201 virtual bool OnUnknownFrame(SpdyStreamId stream_id,
202 int frame_type) OVERRIDE {
203 LOG(FATAL);
204 return false;
207 char* ReleaseBuffer() {
208 CHECK(finished_);
209 return buffer_.release();
212 virtual void OnWindowUpdate(SpdyStreamId stream_id,
213 uint32 delta_window_size) OVERRIDE {
214 LOG(FATAL);
217 size_t size() const {
218 CHECK(finished_);
219 return size_;
222 private:
223 SpdyMajorVersion version_;
224 scoped_ptr<char[]> buffer_;
225 size_t size_;
226 bool finished_;
228 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
231 private:
232 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
235 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
236 public SpdyFramerDebugVisitorInterface {
237 public:
238 // This is larger than our max frame size because header blocks that
239 // are too long can spill over into CONTINUATION frames.
240 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
242 explicit TestSpdyVisitor(SpdyMajorVersion version)
243 : framer_(version),
244 use_compression_(false),
245 error_count_(0),
246 syn_frame_count_(0),
247 syn_reply_frame_count_(0),
248 headers_frame_count_(0),
249 push_promise_frame_count_(0),
250 goaway_count_(0),
251 setting_count_(0),
252 settings_ack_sent_(0),
253 settings_ack_received_(0),
254 continuation_count_(0),
255 altsvc_count_(0),
256 priority_count_(0),
257 test_altsvc_ir_(0),
258 on_unknown_frame_result_(false),
259 last_window_update_stream_(0),
260 last_window_update_delta_(0),
261 last_push_promise_stream_(0),
262 last_push_promise_promised_stream_(0),
263 data_bytes_(0),
264 fin_frame_count_(0),
265 fin_opaque_data_(),
266 fin_flag_count_(0),
267 zero_length_data_frame_count_(0),
268 control_frame_header_data_count_(0),
269 zero_length_control_frame_header_data_count_(0),
270 data_frame_count_(0),
271 last_payload_len_(0),
272 last_frame_len_(0),
273 header_buffer_(new char[kDefaultHeaderBufferSize]),
274 header_buffer_length_(0),
275 header_buffer_size_(kDefaultHeaderBufferSize),
276 header_stream_id_(static_cast<SpdyStreamId>(-1)),
277 header_control_type_(DATA),
278 header_buffer_valid_(false) {}
280 virtual void OnError(SpdyFramer* f) OVERRIDE {
281 LOG(INFO) << "SpdyFramer Error: "
282 << SpdyFramer::ErrorCodeToString(f->error_code());
283 ++error_count_;
286 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
287 size_t length,
288 bool fin) OVERRIDE {
289 ++data_frame_count_;
290 header_stream_id_ = stream_id;
293 virtual void OnStreamFrameData(SpdyStreamId stream_id,
294 const char* data,
295 size_t len,
296 bool fin) OVERRIDE {
297 EXPECT_EQ(header_stream_id_, stream_id);
298 if (len == 0)
299 ++zero_length_data_frame_count_;
301 data_bytes_ += len;
302 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
303 if (len > 0) {
304 for (size_t i = 0 ; i < len; ++i) {
305 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
308 std::cerr << "\", " << len << ")\n";
311 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
312 const char* header_data,
313 size_t len) OVERRIDE {
314 ++control_frame_header_data_count_;
315 CHECK_EQ(header_stream_id_, stream_id);
316 if (len == 0) {
317 ++zero_length_control_frame_header_data_count_;
318 // Indicates end-of-header-block.
319 headers_.clear();
320 CHECK(header_buffer_valid_);
321 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
322 header_buffer_.get(), header_buffer_length_, &headers_);
323 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
324 << "Check failed: header_buffer_length_ == parsed_length "
325 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
326 return true;
328 const size_t available = header_buffer_size_ - header_buffer_length_;
329 if (len > available) {
330 header_buffer_valid_ = false;
331 return false;
333 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
334 header_buffer_length_ += len;
335 return true;
338 virtual void OnSynStream(SpdyStreamId stream_id,
339 SpdyStreamId associated_stream_id,
340 SpdyPriority priority,
341 bool fin,
342 bool unidirectional) OVERRIDE {
343 ++syn_frame_count_;
344 if (framer_.protocol_version() > SPDY3) {
345 InitHeaderStreaming(HEADERS, stream_id);
346 } else {
347 InitHeaderStreaming(SYN_STREAM, stream_id);
349 if (fin) {
350 ++fin_flag_count_;
354 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
355 ++syn_reply_frame_count_;
356 if (framer_.protocol_version() > SPDY3) {
357 InitHeaderStreaming(HEADERS, stream_id);
358 } else {
359 InitHeaderStreaming(SYN_REPLY, stream_id);
361 if (fin) {
362 ++fin_flag_count_;
366 virtual void OnRstStream(SpdyStreamId stream_id,
367 SpdyRstStreamStatus status) OVERRIDE {
368 ++fin_frame_count_;
371 virtual bool OnRstStreamFrameData(const char* rst_stream_data,
372 size_t len) OVERRIDE {
373 if ((rst_stream_data != NULL) && (len > 0)) {
374 fin_opaque_data_ += std::string(rst_stream_data, len);
376 return true;
379 virtual void OnSetting(SpdySettingsIds id,
380 uint8 flags,
381 uint32 value) OVERRIDE {
382 ++setting_count_;
385 virtual void OnSettingsAck() OVERRIDE {
386 DCHECK_LT(SPDY3, framer_.protocol_version());
387 ++settings_ack_received_;
390 virtual void OnSettingsEnd() OVERRIDE {
391 if (framer_.protocol_version() <= SPDY3) { return; }
392 ++settings_ack_sent_;
395 virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
396 DLOG(FATAL);
399 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
400 SpdyGoAwayStatus status) OVERRIDE {
401 ++goaway_count_;
404 virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE {
405 ++headers_frame_count_;
406 InitHeaderStreaming(HEADERS, stream_id);
407 if (fin) {
408 ++fin_flag_count_;
412 virtual void OnWindowUpdate(SpdyStreamId stream_id,
413 uint32 delta_window_size) OVERRIDE {
414 last_window_update_stream_ = stream_id;
415 last_window_update_delta_ = delta_window_size;
418 virtual void OnPushPromise(SpdyStreamId stream_id,
419 SpdyStreamId promised_stream_id,
420 bool end) OVERRIDE {
421 ++push_promise_frame_count_;
422 InitHeaderStreaming(PUSH_PROMISE, stream_id);
423 last_push_promise_stream_ = stream_id;
424 last_push_promise_promised_stream_ = promised_stream_id;
427 virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
428 ++continuation_count_;
431 virtual void OnAltSvc(SpdyStreamId stream_id,
432 uint32 max_age,
433 uint16 port,
434 StringPiece protocol_id,
435 StringPiece host,
436 StringPiece origin) OVERRIDE {
437 test_altsvc_ir_.set_stream_id(stream_id);
438 test_altsvc_ir_.set_max_age(max_age);
439 test_altsvc_ir_.set_port(port);
440 test_altsvc_ir_.set_protocol_id(protocol_id.as_string());
441 test_altsvc_ir_.set_host(host.as_string());
442 if (origin.length() > 0) {
443 test_altsvc_ir_.set_origin(origin.as_string());
445 ++altsvc_count_;
448 virtual void OnPriority(SpdyStreamId stream_id,
449 SpdyStreamId parent_stream_id,
450 uint8 weight,
451 bool exclusive) OVERRIDE {
452 ++priority_count_;
455 virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) OVERRIDE {
456 DLOG(INFO) << "Unknown frame type " << frame_type;
457 return on_unknown_frame_result_;
460 virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
461 SpdyFrameType type,
462 size_t payload_len,
463 size_t frame_len) OVERRIDE {
464 last_payload_len_ = payload_len;
465 last_frame_len_ = frame_len;
468 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
469 SpdyFrameType type,
470 size_t frame_len) OVERRIDE {
471 last_frame_len_ = frame_len;
474 // Convenience function which runs a framer simulation with particular input.
475 void SimulateInFramer(const unsigned char* input, size_t size) {
476 framer_.set_enable_compression(use_compression_);
477 framer_.set_visitor(this);
478 size_t input_remaining = size;
479 const char* input_ptr = reinterpret_cast<const char*>(input);
480 while (input_remaining > 0 &&
481 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
482 // To make the tests more interesting, we feed random (amd small) chunks
483 // into the framer. This simulates getting strange-sized reads from
484 // the socket.
485 const size_t kMaxReadSize = 32;
486 size_t bytes_read =
487 (rand() % min(input_remaining, kMaxReadSize)) + 1;
488 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
489 input_remaining -= bytes_processed;
490 input_ptr += bytes_processed;
494 void InitHeaderStreaming(SpdyFrameType header_control_type,
495 SpdyStreamId stream_id) {
496 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
497 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
498 header_control_type))) {
499 DLOG(FATAL) << "Attempted to init header streaming with "
500 << "invalid control frame type: "
501 << header_control_type;
503 memset(header_buffer_.get(), 0, header_buffer_size_);
504 header_buffer_length_ = 0;
505 header_stream_id_ = stream_id;
506 header_control_type_ = header_control_type;
507 header_buffer_valid_ = true;
508 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
511 // Override the default buffer size (16K). Call before using the framer!
512 void set_header_buffer_size(size_t header_buffer_size) {
513 header_buffer_size_ = header_buffer_size;
514 header_buffer_.reset(new char[header_buffer_size]);
517 static size_t header_data_chunk_max_size() {
518 return SpdyFramer::kHeaderDataChunkMaxSize;
521 SpdyFramer framer_;
522 bool use_compression_;
524 // Counters from the visitor callbacks.
525 int error_count_;
526 int syn_frame_count_;
527 int syn_reply_frame_count_;
528 int headers_frame_count_;
529 int push_promise_frame_count_;
530 int goaway_count_;
531 int setting_count_;
532 int settings_ack_sent_;
533 int settings_ack_received_;
534 int continuation_count_;
535 int altsvc_count_;
536 int priority_count_;
537 SpdyAltSvcIR test_altsvc_ir_;
538 bool on_unknown_frame_result_;
539 SpdyStreamId last_window_update_stream_;
540 uint32 last_window_update_delta_;
541 SpdyStreamId last_push_promise_stream_;
542 SpdyStreamId last_push_promise_promised_stream_;
543 int data_bytes_;
544 int fin_frame_count_; // The count of RST_STREAM type frames received.
545 std::string fin_opaque_data_;
546 int fin_flag_count_; // The count of frames with the FIN flag set.
547 int zero_length_data_frame_count_; // The count of zero-length data frames.
548 int control_frame_header_data_count_; // The count of chunks received.
549 // The count of zero-length control frame header data chunks received.
550 int zero_length_control_frame_header_data_count_;
551 int data_frame_count_;
552 size_t last_payload_len_;
553 size_t last_frame_len_;
555 // Header block streaming state:
556 scoped_ptr<char[]> header_buffer_;
557 size_t header_buffer_length_;
558 size_t header_buffer_size_;
559 SpdyStreamId header_stream_id_;
560 SpdyFrameType header_control_type_;
561 bool header_buffer_valid_;
562 SpdyHeaderBlock headers_;
565 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
566 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
567 const SpdyFramer& framer) {
568 SpdyFrameReader reader(frame->data(), frame->size());
569 if (framer.protocol_version() > SPDY3) {
570 reader.Seek(3); // Seek past the frame length.
571 } else {
572 reader.Seek(2); // Seek past the frame length.
574 SpdyFrameType frame_type;
575 if (framer.protocol_version() > SPDY3) {
576 uint8 serialized_type;
577 reader.ReadUInt8(&serialized_type);
578 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
579 serialized_type);
580 DCHECK_EQ(HEADERS, frame_type);
581 uint8 flags;
582 reader.ReadUInt8(&flags);
583 if (flags & HEADERS_FLAG_PRIORITY) {
584 frame_type = SYN_STREAM;
586 } else {
587 uint16 serialized_type;
588 reader.ReadUInt16(&serialized_type);
589 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
590 serialized_type);
591 DCHECK(frame_type == HEADERS ||
592 frame_type == SYN_STREAM) << frame_type;
595 if (frame_type == SYN_STREAM) {
596 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
597 frame->size() - framer.GetSynStreamMinimumSize());
598 } else {
599 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
600 frame->size() - framer.GetHeadersMinimumSize());
604 } // namespace test
606 } // namespace net
608 using net::test::SetFrameLength;
609 using net::test::SetFrameFlags;
610 using net::test::CompareCharArraysWithHexError;
611 using net::test::SpdyFramerTestUtil;
612 using net::test::TestSpdyVisitor;
613 using net::test::GetSerializedHeaders;
615 namespace net {
617 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
618 protected:
619 virtual void SetUp() {
620 spdy_version_ = GetParam();
621 spdy_version_ch_ = static_cast<unsigned char>(
622 SpdyConstants::SerializeMajorVersion(spdy_version_));
625 void CompareFrame(const string& description,
626 const SpdyFrame& actual_frame,
627 const unsigned char* expected,
628 const int expected_len) {
629 const unsigned char* actual =
630 reinterpret_cast<const unsigned char*>(actual_frame.data());
631 CompareCharArraysWithHexError(
632 description, actual, actual_frame.size(), expected, expected_len);
635 void CompareFrames(const string& description,
636 const SpdyFrame& expected_frame,
637 const SpdyFrame& actual_frame) {
638 CompareCharArraysWithHexError(
639 description,
640 reinterpret_cast<const unsigned char*>(expected_frame.data()),
641 expected_frame.size(),
642 reinterpret_cast<const unsigned char*>(actual_frame.data()),
643 actual_frame.size());
646 // Returns true if the two header blocks have equivalent content.
647 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
648 const SpdyHeaderBlock* actual) {
649 if (expected->size() != actual->size()) {
650 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
651 << actual->size() << ".";
652 return false;
654 for (SpdyHeaderBlock::const_iterator it = expected->begin();
655 it != expected->end();
656 ++it) {
657 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
658 if (it2 == actual->end()) {
659 LOG(ERROR) << "Expected header name '" << it->first << "'.";
660 return false;
662 if (it->second.compare(it2->second) != 0) {
663 LOG(ERROR) << "Expected header named '" << it->first
664 << "' to have a value of '" << it->second
665 << "'. The actual value received was '" << it2->second
666 << "'.";
667 return false;
670 return true;
673 bool IsSpdy2() { return spdy_version_ == SPDY2; }
674 bool IsSpdy3() { return spdy_version_ == SPDY3; }
675 bool IsSpdy4() { return spdy_version_ == SPDY4; }
676 bool IsSpdy5() { return spdy_version_ == SPDY5; }
678 // Version of SPDY protocol to be used.
679 SpdyMajorVersion spdy_version_;
680 unsigned char spdy_version_ch_;
683 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
684 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
685 SpdyFramerTest,
686 ::testing::Values(SPDY2, SPDY3, SPDY4));
688 // Test that we ignore cookie where both name and value are empty.
689 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
690 if (spdy_version_ > SPDY3) {
691 // Not implemented for hpack.
692 return;
695 SpdyFramer framer(spdy_version_);
696 framer.set_enable_compression(true);
697 SpdyHeadersIR headers(1);
698 headers.set_priority(1);
699 headers.SetHeader("cookie",
700 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
701 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
702 EXPECT_TRUE(frame.get() != NULL);
704 TestSpdyVisitor visitor(spdy_version_);
705 visitor.use_compression_ = true;
706 visitor.SimulateInFramer(
707 reinterpret_cast<unsigned char*>(frame->data()),
708 frame->size());
710 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
711 EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
712 &visitor.headers_));
713 EXPECT_EQ(1u, visitor.headers_.size());
714 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
717 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
718 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
719 SpdyFramer framer(spdy_version_);
720 framer.set_enable_compression(false);
722 // Encode the header block into a Headers frame.
723 SpdyHeadersIR headers(1);
724 headers.set_priority(1);
725 headers.SetHeader("alpha", "beta");
726 headers.SetHeader("gamma", "charlie");
727 headers.SetHeader("cookie", "key1=value1; key2=value2");
728 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
729 EXPECT_TRUE(frame.get() != NULL);
731 TestSpdyVisitor visitor(spdy_version_);
732 visitor.use_compression_ = false;
733 visitor.SimulateInFramer(
734 reinterpret_cast<unsigned char*>(frame->data()),
735 frame->size());
737 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
738 EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
739 &visitor.headers_));
742 // Test that if there's not a full frame, we fail to parse it.
743 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
744 SpdyFramer framer(spdy_version_);
745 framer.set_enable_compression(false);
747 // Encode the header block into a Headers frame.
748 SpdyHeadersIR headers(1);
749 headers.set_priority(1);
750 headers.SetHeader("alpha", "beta");
751 headers.SetHeader("gamma", "charlie");
752 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
753 EXPECT_TRUE(frame.get() != NULL);
755 TestSpdyVisitor visitor(spdy_version_);
756 visitor.use_compression_ = false;
757 visitor.SimulateInFramer(
758 reinterpret_cast<unsigned char*>(frame->data()),
759 frame->size() - 2);
761 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
762 EXPECT_EQ(0u, visitor.headers_.size());
765 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
766 // (but don't crash).
767 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
768 if (spdy_version_ > SPDY3) {
769 return;
771 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
772 SpdyFramer framer(spdy_version_);
773 framer.set_visitor(&visitor);
775 SpdySynReplyIR syn_reply(0);
776 syn_reply.SetHeader("alpha", "beta");
777 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
778 ASSERT_TRUE(frame.get() != NULL);
780 // We shouldn't have to read the whole frame before we signal an error.
781 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
782 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
783 EXPECT_TRUE(framer.HasError());
784 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
785 << SpdyFramer::ErrorCodeToString(framer.error_code());
788 // Test that if we receive a HEADERS with stream ID zero, we signal an error
789 // (but don't crash).
790 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
791 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
792 SpdyFramer framer(spdy_version_);
793 framer.set_visitor(&visitor);
795 SpdyHeadersIR headers_ir(0);
796 headers_ir.SetHeader("alpha", "beta");
797 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
798 ASSERT_TRUE(frame.get() != NULL);
800 // We shouldn't have to read the whole frame before we signal an error.
801 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
802 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
803 EXPECT_TRUE(framer.HasError());
804 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
805 << SpdyFramer::ErrorCodeToString(framer.error_code());
808 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
809 // error (but don't crash).
810 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
811 if (spdy_version_ <= SPDY3) {
812 return;
815 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
816 SpdyFramer framer(spdy_version_);
817 framer.set_visitor(&visitor);
819 SpdyPushPromiseIR push_promise(0, 4);
820 push_promise.SetHeader("alpha", "beta");
821 scoped_ptr<SpdySerializedFrame> frame(
822 framer.SerializePushPromise(push_promise));
823 ASSERT_TRUE(frame.get() != NULL);
825 // We shouldn't have to read the whole frame before we signal an error.
826 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
827 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
828 EXPECT_TRUE(framer.HasError());
829 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
830 << SpdyFramer::ErrorCodeToString(framer.error_code());
833 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
834 // signal an error (but don't crash).
835 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
836 if (spdy_version_ <= SPDY3) {
837 return;
840 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
841 SpdyFramer framer(spdy_version_);
842 framer.set_visitor(&visitor);
844 SpdyPushPromiseIR push_promise(3, 0);
845 push_promise.SetHeader("alpha", "beta");
846 scoped_ptr<SpdySerializedFrame> frame(
847 framer.SerializePushPromise(push_promise));
848 ASSERT_TRUE(frame.get() != NULL);
850 // We shouldn't have to read the whole frame before we signal an error.
851 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
852 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
853 EXPECT_TRUE(framer.HasError());
854 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
855 << SpdyFramer::ErrorCodeToString(framer.error_code());
858 TEST_P(SpdyFramerTest, DuplicateHeader) {
859 if (spdy_version_ > SPDY3) {
860 // TODO(jgraettinger): Punting on this because we haven't determined
861 // whether duplicate HPACK headers other than Cookie are an error.
862 // If they are, this will need to be updated to use HpackOutputStream.
863 return;
865 SpdyFramer framer(spdy_version_);
866 // Frame builder with plentiful buffer size.
867 SpdyFrameBuilder frame(1024, spdy_version_);
868 if (spdy_version_ <= SPDY3) {
869 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
870 frame.WriteUInt32(3); // stream_id
871 frame.WriteUInt32(0); // associated stream id
872 frame.WriteUInt16(0); // Priority.
873 } else {
874 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
875 frame.WriteUInt32(framer.GetHighestPriority());
878 if (IsSpdy2()) {
879 frame.WriteUInt16(2); // Number of headers.
880 frame.WriteString("name");
881 frame.WriteString("value1");
882 frame.WriteString("name");
883 frame.WriteString("value2");
884 } else {
885 frame.WriteUInt32(2); // Number of headers.
886 frame.WriteStringPiece32("name");
887 frame.WriteStringPiece32("value1");
888 frame.WriteStringPiece32("name");
889 frame.WriteStringPiece32("value2");
891 // write the length
892 frame.RewriteLength(framer);
894 SpdyHeaderBlock new_headers;
895 framer.set_enable_compression(false);
896 scoped_ptr<SpdyFrame> control_frame(frame.take());
897 base::StringPiece serialized_headers =
898 GetSerializedHeaders(control_frame.get(), framer);
899 // This should fail because duplicate headers are verboten by the spec.
900 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
901 serialized_headers.size(),
902 &new_headers));
905 TEST_P(SpdyFramerTest, MultiValueHeader) {
906 SpdyFramer framer(spdy_version_);
907 // Frame builder with plentiful buffer size.
908 SpdyFrameBuilder frame(1024, spdy_version_);
909 if (spdy_version_ <= SPDY3) {
910 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
911 frame.WriteUInt32(3); // stream_id
912 frame.WriteUInt32(0); // associated stream id
913 frame.WriteUInt16(0); // Priority.
914 } else {
915 frame.BeginNewFrame(framer,
916 HEADERS,
917 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
919 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
920 frame.WriteUInt8(255); // Priority weight.
923 string value("value1\0value2", 13);
924 if (IsSpdy2()) {
925 frame.WriteUInt16(1); // Number of headers.
926 frame.WriteString("name");
927 frame.WriteString(value);
928 } else if (spdy_version_ > SPDY3) {
929 // TODO(jgraettinger): If this pattern appears again, move to test class.
930 std::map<string, string> header_set;
931 header_set["name"] = value;
932 string buffer;
933 HpackEncoder encoder(ObtainHpackHuffmanTable());
934 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
935 frame.WriteBytes(&buffer[0], buffer.size());
936 } else {
937 frame.WriteUInt32(1); // Number of headers.
938 frame.WriteStringPiece32("name");
939 frame.WriteStringPiece32(value);
941 // write the length
942 frame.RewriteLength(framer);
944 framer.set_enable_compression(false);
945 scoped_ptr<SpdyFrame> control_frame(frame.take());
947 TestSpdyVisitor visitor(spdy_version_);
948 visitor.use_compression_ = false;
949 visitor.SimulateInFramer(
950 reinterpret_cast<unsigned char*>(control_frame->data()),
951 control_frame->size());
953 EXPECT_THAT(visitor.headers_, ElementsAre(
954 Pair("name", value)));
957 TEST_P(SpdyFramerTest, BasicCompression) {
958 if (spdy_version_ > SPDY3) {
959 // Deflate compression doesn't apply to HPACK.
960 return;
962 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
963 SpdyFramer framer(spdy_version_);
964 framer.set_debug_visitor(visitor.get());
965 SpdySynStreamIR syn_stream(1);
966 syn_stream.set_priority(1);
967 syn_stream.SetHeader("server", "SpdyServer 1.0");
968 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
969 syn_stream.SetHeader("status", "200");
970 syn_stream.SetHeader("version", "HTTP/1.1");
971 syn_stream.SetHeader("content-type", "text/html");
972 syn_stream.SetHeader("content-length", "12");
973 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
974 size_t uncompressed_size1 = visitor->last_payload_len_;
975 size_t compressed_size1 =
976 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
977 if (IsSpdy2()) {
978 EXPECT_EQ(139u, uncompressed_size1);
979 #if defined(USE_SYSTEM_ZLIB)
980 EXPECT_EQ(155u, compressed_size1);
981 #else // !defined(USE_SYSTEM_ZLIB)
982 EXPECT_EQ(135u, compressed_size1);
983 #endif // !defined(USE_SYSTEM_ZLIB)
984 } else {
985 EXPECT_EQ(165u, uncompressed_size1);
986 #if defined(USE_SYSTEM_ZLIB)
987 EXPECT_EQ(181u, compressed_size1);
988 #else // !defined(USE_SYSTEM_ZLIB)
989 EXPECT_EQ(117u, compressed_size1);
990 #endif // !defined(USE_SYSTEM_ZLIB)
992 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
993 size_t uncompressed_size2 = visitor->last_payload_len_;
994 size_t compressed_size2 =
995 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
997 // Expect the second frame to be more compact than the first.
998 EXPECT_LE(frame2->size(), frame1->size());
1000 // Decompress the first frame
1001 scoped_ptr<SpdyFrame> frame3(
1002 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
1004 // Decompress the second frame
1005 visitor.reset(new TestSpdyVisitor(spdy_version_));
1006 framer.set_debug_visitor(visitor.get());
1007 scoped_ptr<SpdyFrame> frame4(
1008 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1009 size_t uncompressed_size4 =
1010 frame4->size() - framer.GetSynStreamMinimumSize();
1011 size_t compressed_size4 =
1012 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1013 if (IsSpdy2()) {
1014 EXPECT_EQ(139u, uncompressed_size4);
1015 #if defined(USE_SYSTEM_ZLIB)
1016 EXPECT_EQ(149u, compressed_size4);
1017 #else // !defined(USE_SYSTEM_ZLIB)
1018 EXPECT_EQ(101u, compressed_size4);
1019 #endif // !defined(USE_SYSTEM_ZLIB)
1020 } else {
1021 EXPECT_EQ(165u, uncompressed_size4);
1022 #if defined(USE_SYSTEM_ZLIB)
1023 EXPECT_EQ(175u, compressed_size4);
1024 #else // !defined(USE_SYSTEM_ZLIB)
1025 EXPECT_EQ(102u, compressed_size4);
1026 #endif // !defined(USE_SYSTEM_ZLIB)
1029 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1030 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1031 EXPECT_EQ(compressed_size2, compressed_size4);
1033 // Expect frames 3 & 4 to be the same.
1034 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1036 // Expect frames 3 to be the same as a uncompressed frame created
1037 // from scratch.
1038 framer.set_enable_compression(false);
1039 scoped_ptr<SpdyFrame> uncompressed_frame(
1040 framer.SerializeSynStream(syn_stream));
1041 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1044 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1045 // See crbug.com/172383
1046 SpdyHeadersIR headers(1);
1047 headers.SetHeader("server", "SpdyServer 1.0");
1048 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1049 headers.SetHeader("status", "200");
1050 headers.SetHeader("version", "HTTP/1.1");
1051 headers.SetHeader("content-type", "text/html");
1052 headers.SetHeader("content-length", "12");
1053 headers.SetHeader("x-empty-header", "");
1055 SpdyFramer framer(spdy_version_);
1056 framer.set_enable_compression(true);
1057 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1060 TEST_P(SpdyFramerTest, Basic) {
1061 const unsigned char kV2Input[] = {
1062 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1063 0x00, 0x00, 0x00, 0x14,
1064 0x00, 0x00, 0x00, 0x01,
1065 0x00, 0x00, 0x00, 0x00,
1066 0x00, 0x00, 0x00, 0x01,
1067 0x00, 0x02, 'h', 'h',
1068 0x00, 0x02, 'v', 'v',
1070 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1071 0x00, 0x00, 0x00, 0x18,
1072 0x00, 0x00, 0x00, 0x01,
1073 0x00, 0x00, 0x00, 0x02,
1074 0x00, 0x02, 'h', '2',
1075 0x00, 0x02, 'v', '2',
1076 0x00, 0x02, 'h', '3',
1077 0x00, 0x02, 'v', '3',
1079 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1080 0x00, 0x00, 0x00, 0x0c,
1081 0xde, 0xad, 0xbe, 0xef,
1082 0xde, 0xad, 0xbe, 0xef,
1083 0xde, 0xad, 0xbe, 0xef,
1085 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1086 0x00, 0x00, 0x00, 0x0c,
1087 0x00, 0x00, 0x00, 0x03,
1088 0x00, 0x00, 0x00, 0x00,
1089 0x00, 0x00, 0x00, 0x00,
1091 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1092 0x00, 0x00, 0x00, 0x08,
1093 0xde, 0xad, 0xbe, 0xef,
1094 0xde, 0xad, 0xbe, 0xef,
1096 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1097 0x00, 0x00, 0x00, 0x04,
1098 0xde, 0xad, 0xbe, 0xef,
1100 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1101 0x00, 0x00, 0x00, 0x08,
1102 0x00, 0x00, 0x00, 0x01,
1103 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1105 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1106 0x00, 0x00, 0x00, 0x00,
1108 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1109 0x00, 0x00, 0x00, 0x08,
1110 0x00, 0x00, 0x00, 0x03,
1111 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1114 const unsigned char kV3Input[] = {
1115 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1116 0x00, 0x00, 0x00, 0x1a,
1117 0x00, 0x00, 0x00, 0x01,
1118 0x00, 0x00, 0x00, 0x00,
1119 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x01, 0x00, 0x00,
1121 0x00, 0x02, 'h', 'h',
1122 0x00, 0x00, 0x00, 0x02,
1123 'v', 'v',
1125 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1126 0x00, 0x00, 0x00, 0x20,
1127 0x00, 0x00, 0x00, 0x01,
1128 0x00, 0x00, 0x00, 0x02,
1129 0x00, 0x00, 0x00, 0x02,
1130 'h', '2',
1131 0x00, 0x00, 0x00, 0x02,
1132 'v', '2', 0x00, 0x00,
1133 0x00, 0x02, 'h', '3',
1134 0x00, 0x00, 0x00, 0x02,
1135 'v', '3',
1137 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1138 0x00, 0x00, 0x00, 0x0c,
1139 0xde, 0xad, 0xbe, 0xef,
1140 0xde, 0xad, 0xbe, 0xef,
1141 0xde, 0xad, 0xbe, 0xef,
1143 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1144 0x00, 0x00, 0x00, 0x0e,
1145 0x00, 0x00, 0x00, 0x03,
1146 0x00, 0x00, 0x00, 0x00,
1147 0x00, 0x00, 0x00, 0x00,
1148 0x00, 0x00,
1150 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1151 0x00, 0x00, 0x00, 0x08,
1152 0xde, 0xad, 0xbe, 0xef,
1153 0xde, 0xad, 0xbe, 0xef,
1155 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1156 0x00, 0x00, 0x00, 0x04,
1157 0xde, 0xad, 0xbe, 0xef,
1159 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1160 0x00, 0x00, 0x00, 0x08,
1161 0x00, 0x00, 0x00, 0x01,
1162 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1164 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1165 0x00, 0x00, 0x00, 0x00,
1167 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1168 0x00, 0x00, 0x00, 0x08,
1169 0x00, 0x00, 0x00, 0x03,
1170 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1173 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1174 // HEADERS frames with PRIORITY and END_HEADERS set.
1175 const unsigned char kV4Input[] = {
1176 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1177 0x24, 0x00, 0x00, 0x00,
1178 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1179 0x00, 0x82, // :method: GET
1181 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1182 0x04, 0x00, 0x00, 0x00, // Stream 1
1183 0x01, 0x8c, // :status: 200
1185 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1186 0x00, 0x00, 0x00, 0x00,
1187 0x01, 0xde, 0xad, 0xbe,
1188 0xef, 0xde, 0xad, 0xbe,
1189 0xef, 0xde, 0xad, 0xbe,
1190 0xef,
1192 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1193 0x24, 0x00, 0x00, 0x00,
1194 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1195 0x00, 0x82, // :method: GET
1197 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1198 0x00, 0x00, 0x00, 0x00,
1199 0x03, 0xde, 0xad, 0xbe,
1200 0xef, 0xde, 0xad, 0xbe,
1201 0xef,
1203 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1204 0x00, 0x00, 0x00, 0x00,
1205 0x01, 0xde, 0xad, 0xbe,
1206 0xef,
1208 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1209 0x00, 0x00, 0x00, 0x00,
1210 0x01, 0x00, 0x00, 0x00,
1211 0x08, // RST_STREAM_CANCEL
1213 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1214 0x00, 0x00, 0x00, 0x00,
1215 0x03,
1217 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1218 0x00, 0x00, 0x00, 0x00,
1219 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1220 0x08, 0x52, 0x45, 0x53, // opaque data
1221 0x45, 0x54, 0x53, 0x54,
1222 0x52, 0x45, 0x41, 0x4d,
1225 TestSpdyVisitor visitor(spdy_version_);
1226 if (IsSpdy2()) {
1227 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1228 } else if (IsSpdy3()) {
1229 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1230 } else {
1231 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1234 EXPECT_EQ(2, visitor.syn_frame_count_);
1235 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1236 EXPECT_EQ(1, visitor.headers_frame_count_);
1237 EXPECT_EQ(24, visitor.data_bytes_);
1239 EXPECT_EQ(0, visitor.error_count_);
1240 EXPECT_EQ(2, visitor.fin_frame_count_);
1242 if (IsSpdy4()) {
1243 base::StringPiece reset_stream = "RESETSTREAM";
1244 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1245 } else {
1246 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1249 EXPECT_EQ(0, visitor.fin_flag_count_);
1250 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1251 EXPECT_EQ(4, visitor.data_frame_count_);
1252 visitor.fin_opaque_data_.clear();
1255 // Test that the FIN flag on a data frame signifies EOF.
1256 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1257 const unsigned char kV2Input[] = {
1258 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1259 0x00, 0x00, 0x00, 0x14,
1260 0x00, 0x00, 0x00, 0x01,
1261 0x00, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x01,
1263 0x00, 0x02, 'h', 'h',
1264 0x00, 0x02, 'v', 'v',
1266 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1267 0x00, 0x00, 0x00, 0x10,
1268 0x00, 0x00, 0x00, 0x01,
1269 0x00, 0x00, 0x00, 0x01,
1270 0x00, 0x02, 'a', 'a',
1271 0x00, 0x02, 'b', 'b',
1273 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1274 0x00, 0x00, 0x00, 0x0c,
1275 0xde, 0xad, 0xbe, 0xef,
1276 0xde, 0xad, 0xbe, 0xef,
1277 0xde, 0xad, 0xbe, 0xef,
1279 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1280 0x01, 0x00, 0x00, 0x04,
1281 0xde, 0xad, 0xbe, 0xef,
1283 const unsigned char kV3Input[] = {
1284 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1285 0x00, 0x00, 0x00, 0x1a,
1286 0x00, 0x00, 0x00, 0x01,
1287 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x01, 0x00, 0x00,
1290 0x00, 0x02, 'h', 'h',
1291 0x00, 0x00, 0x00, 0x02,
1292 'v', 'v',
1294 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1295 0x00, 0x00, 0x00, 0x14,
1296 0x00, 0x00, 0x00, 0x01,
1297 0x00, 0x00, 0x00, 0x01,
1298 0x00, 0x00, 0x00, 0x02,
1299 'a', 'a', 0x00, 0x00,
1300 0x00, 0x02, 'b', 'b',
1302 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1303 0x00, 0x00, 0x00, 0x0c,
1304 0xde, 0xad, 0xbe, 0xef,
1305 0xde, 0xad, 0xbe, 0xef,
1306 0xde, 0xad, 0xbe, 0xef,
1308 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1309 0x01, 0x00, 0x00, 0x04,
1310 0xde, 0xad, 0xbe, 0xef,
1313 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1314 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1315 const unsigned char kV4Input[] = {
1316 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1317 0x24, 0x00, 0x00, 0x00, // Stream 1
1318 0x01, 0x00, 0x00, 0x00, // Priority 0
1319 0x00, 0x82, // :method: GET
1321 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1322 0x04, 0x00, 0x00, 0x00, // Stream 1
1323 0x01, 0x8c, // :status: 200
1325 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1326 0x00, 0x00, 0x00, 0x00,
1327 0x01, 0xde, 0xad, 0xbe,
1328 0xef, 0xde, 0xad, 0xbe,
1329 0xef, 0xde, 0xad, 0xbe,
1330 0xef,
1332 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1333 0x01, 0x00, 0x00, 0x00,
1334 0x01, 0xde, 0xad, 0xbe,
1335 0xef,
1338 TestSpdyVisitor visitor(spdy_version_);
1339 if (IsSpdy2()) {
1340 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1341 } else if (IsSpdy3()) {
1342 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1343 } else {
1344 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1347 EXPECT_EQ(0, visitor.error_count_);
1348 EXPECT_EQ(1, visitor.syn_frame_count_);
1349 if (IsSpdy4()) {
1350 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1351 EXPECT_EQ(1, visitor.headers_frame_count_);
1352 } else {
1353 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1354 EXPECT_EQ(0, visitor.headers_frame_count_);
1356 EXPECT_EQ(16, visitor.data_bytes_);
1357 EXPECT_EQ(0, visitor.fin_frame_count_);
1358 EXPECT_EQ(0, visitor.fin_flag_count_);
1359 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1360 EXPECT_EQ(2, visitor.data_frame_count_);
1363 // Test that the FIN flag on a SYN reply frame signifies EOF.
1364 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1365 const unsigned char kV2Input[] = {
1366 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1367 0x01, 0x00, 0x00, 0x00,
1368 0x14, 0x00, 0x00, 0x00,
1369 0x01, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00,
1371 0x01, 0x00, 0x02, 'h',
1372 'h', 0x00, 0x02, 'v',
1373 'v',
1375 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1376 0x02, 0x01, 0x00, 0x00,
1377 0x10, 0x00, 0x00, 0x00,
1378 0x01, 0x00, 0x00, 0x00,
1379 0x01, 0x00, 0x02, 'a',
1380 'a', 0x00, 0x02, 'b',
1381 'b',
1383 const unsigned char kV3Input[] = {
1384 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1385 0x01, 0x00, 0x00, 0x00,
1386 0x1a, 0x00, 0x00, 0x00,
1387 0x01, 0x00, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00,
1389 0x00, 0x00, 0x01, 0x00,
1390 0x00, 0x00, 0x02, 'h',
1391 'h', 0x00, 0x00, 0x00,
1392 0x02, 'v', 'v',
1394 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1395 0x02, 0x01, 0x00, 0x00,
1396 0x14, 0x00, 0x00, 0x00,
1397 0x01, 0x00, 0x00, 0x00,
1398 0x01, 0x00, 0x00, 0x00,
1399 0x02, 'a', 'a', 0x00,
1400 0x00, 0x00, 0x02, 'b',
1401 'b',
1404 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1405 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1406 const unsigned char kV4Input[] = {
1407 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1408 0x24, 0x00, 0x00, 0x00,
1409 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1410 0x00, 0x82, // :method: GET
1412 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1413 0x05, 0x00, 0x00, 0x00,
1414 0x01, 0x8c, // Stream 1, :status: 200
1417 TestSpdyVisitor visitor(spdy_version_);
1418 if (IsSpdy2()) {
1419 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1420 } else if (IsSpdy3()) {
1421 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1422 } else {
1423 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1426 EXPECT_EQ(0, visitor.error_count_);
1427 EXPECT_EQ(1, visitor.syn_frame_count_);
1428 if (IsSpdy4()) {
1429 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1430 EXPECT_EQ(1, visitor.headers_frame_count_);
1431 } else {
1432 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1433 EXPECT_EQ(0, visitor.headers_frame_count_);
1435 EXPECT_EQ(0, visitor.data_bytes_);
1436 EXPECT_EQ(0, visitor.fin_frame_count_);
1437 EXPECT_EQ(1, visitor.fin_flag_count_);
1438 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1439 EXPECT_EQ(0, visitor.data_frame_count_);
1442 TEST_P(SpdyFramerTest, HeaderCompression) {
1443 if (spdy_version_ > SPDY3) {
1444 // Deflate compression doesn't apply to HPACK.
1445 return;
1447 SpdyFramer send_framer(spdy_version_);
1448 SpdyFramer recv_framer(spdy_version_);
1450 send_framer.set_enable_compression(true);
1451 recv_framer.set_enable_compression(true);
1453 const char kHeader1[] = "header1";
1454 const char kHeader2[] = "header2";
1455 const char kHeader3[] = "header3";
1456 const char kValue1[] = "value1";
1457 const char kValue2[] = "value2";
1458 const char kValue3[] = "value3";
1460 // SYN_STREAM #1
1461 SpdyHeaderBlock block;
1462 block[kHeader1] = kValue1;
1463 block[kHeader2] = kValue2;
1464 SpdySynStreamIR syn_ir_1(1);
1465 syn_ir_1.set_name_value_block(block);
1466 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1467 EXPECT_TRUE(syn_frame_1.get() != NULL);
1469 // SYN_STREAM #2
1470 block[kHeader3] = kValue3;
1471 SpdySynStreamIR syn_stream(3);
1472 syn_stream.set_name_value_block(block);
1473 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1474 EXPECT_TRUE(syn_frame_2.get() != NULL);
1476 // Now start decompressing
1477 scoped_ptr<SpdyFrame> decompressed;
1478 scoped_ptr<SpdyFrame> uncompressed;
1479 base::StringPiece serialized_headers;
1480 SpdyHeaderBlock decompressed_headers;
1482 // Decompress SYN_STREAM #1
1483 decompressed.reset(
1484 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1485 EXPECT_TRUE(decompressed.get() != NULL);
1486 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1487 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1488 serialized_headers.size(),
1489 &decompressed_headers));
1490 EXPECT_EQ(2u, decompressed_headers.size());
1491 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1492 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1494 // Decompress SYN_STREAM #2
1495 decompressed.reset(
1496 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1497 EXPECT_TRUE(decompressed.get() != NULL);
1498 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1499 decompressed_headers.clear();
1500 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1501 serialized_headers.size(),
1502 &decompressed_headers));
1503 EXPECT_EQ(3u, decompressed_headers.size());
1504 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1505 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1506 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1509 // Verify we can decompress the stream even if handed over to the
1510 // framer 1 byte at a time.
1511 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1512 SpdyFramer send_framer(spdy_version_);
1514 send_framer.set_enable_compression(true);
1516 const char kHeader1[] = "header1";
1517 const char kHeader2[] = "header2";
1518 const char kValue1[] = "value1";
1519 const char kValue2[] = "value2";
1521 SpdyHeadersIR headers(1);
1522 headers.SetHeader(kHeader1, kValue1);
1523 headers.SetHeader(kHeader2, kValue2);
1524 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1525 EXPECT_TRUE(headers_frame.get() != NULL);
1527 const char bytes[] = "this is a test test test test test!";
1528 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1529 data_ir.set_fin(true);
1530 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1531 EXPECT_TRUE(send_frame.get() != NULL);
1533 // Run the inputs through the framer.
1534 TestSpdyVisitor visitor(spdy_version_);
1535 visitor.use_compression_ = true;
1536 const unsigned char* data;
1537 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1538 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1539 visitor.SimulateInFramer(data + idx, 1);
1540 ASSERT_EQ(0, visitor.error_count_);
1542 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1543 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1544 visitor.SimulateInFramer(data + idx, 1);
1545 ASSERT_EQ(0, visitor.error_count_);
1548 EXPECT_EQ(0, visitor.error_count_);
1549 EXPECT_EQ(0, visitor.syn_frame_count_);
1550 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1551 EXPECT_EQ(1, visitor.headers_frame_count_);
1552 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1553 EXPECT_EQ(0, visitor.fin_frame_count_);
1554 EXPECT_EQ(0, visitor.fin_flag_count_);
1555 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1556 EXPECT_EQ(1, visitor.data_frame_count_);
1559 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1560 SpdyFramer framer(spdy_version_);
1561 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1562 SpdyWindowUpdateIR(1, 0x12345678)));
1564 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1565 const unsigned char kV3FrameData[] = { // Also applies for V2.
1566 0x80, spdy_version_ch_, 0x00, 0x09,
1567 0x00, 0x00, 0x00, 0x08,
1568 0x00, 0x00, 0x00, 0x01,
1569 0x12, 0x34, 0x56, 0x78
1571 const unsigned char kV4FrameData[] = {
1572 0x00, 0x00, 0x04, 0x08,
1573 0x00, 0x00, 0x00, 0x00,
1574 0x01, 0x12, 0x34, 0x56,
1575 0x78
1578 if (IsSpdy4()) {
1579 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1580 } else {
1581 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1585 TEST_P(SpdyFramerTest, CreateDataFrame) {
1586 SpdyFramer framer(spdy_version_);
1589 const char kDescription[] = "'hello' data frame, no FIN";
1590 const unsigned char kV3FrameData[] = { // Also applies for V2.
1591 0x00, 0x00, 0x00, 0x01,
1592 0x00, 0x00, 0x00, 0x05,
1593 'h', 'e', 'l', 'l',
1596 const unsigned char kV4FrameData[] = {
1597 0x00, 0x00, 0x05, 0x00,
1598 0x00, 0x00, 0x00, 0x00,
1599 0x01, 'h', 'e', 'l',
1600 'l', 'o'
1602 const char bytes[] = "hello";
1604 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1605 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1606 if (IsSpdy4()) {
1607 CompareFrame(
1608 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1609 } else {
1610 CompareFrame(
1611 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1614 SpdyDataIR data_header_ir(1);
1615 data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
1616 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1617 data_header_ir));
1618 CompareCharArraysWithHexError(
1619 kDescription,
1620 reinterpret_cast<const unsigned char*>(frame->data()),
1621 framer.GetDataFrameMinimumSize(),
1622 IsSpdy4() ? kV4FrameData : kV3FrameData,
1623 framer.GetDataFrameMinimumSize());
1627 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1628 const unsigned char kV3FrameData[] = { // Also applies for V2.
1629 0x00, 0x00, 0x00, 0x01,
1630 0x00, 0x00, 0x00, 0x05,
1631 'h', 'e', 'l', 'l',
1635 const unsigned char kV4FrameData[] = {
1636 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1637 0x08, 0x00, 0x00, 0x00,
1638 0x01, 0xf7, // Pad length field.
1639 'h', 'e', 'l', 'l', // Data
1640 'o',
1641 // Padding of 247 zeros.
1642 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1643 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1644 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1645 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1646 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1647 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1648 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1649 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1650 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1651 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1652 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1653 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1654 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1655 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1656 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1657 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1658 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1659 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1660 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1662 const char bytes[] = "hello";
1664 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1665 // 247 zeros and the pad length field make the overall padding to be 248
1666 // bytes.
1667 data_ir.set_padding_len(248);
1668 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1669 if (IsSpdy4()) {
1670 CompareFrame(
1671 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1672 } else {
1673 CompareFrame(
1674 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1677 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1678 CompareCharArraysWithHexError(
1679 kDescription,
1680 reinterpret_cast<const unsigned char*>(frame->data()),
1681 framer.GetDataFrameMinimumSize(),
1682 IsSpdy4() ? kV4FrameData : kV3FrameData,
1683 framer.GetDataFrameMinimumSize());
1687 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1688 const unsigned char kV3FrameData[] = { // Also applies for V2.
1689 0x00, 0x00, 0x00, 0x01,
1690 0x00, 0x00, 0x00, 0x05,
1691 'h', 'e', 'l', 'l',
1695 const unsigned char kV4FrameData[] = {
1696 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1697 0x08, 0x00, 0x00, 0x00,
1698 0x01, 0x07, // Pad length field.
1699 'h', 'e', 'l', 'l', // Data
1700 'o',
1701 '0', '0', '0', '0', // Padding
1702 '0', '0', '0'
1704 const char bytes[] = "hello";
1706 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1707 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1708 data_ir.set_padding_len(8);
1709 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1710 if (IsSpdy4()) {
1711 CompareFrame(
1712 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1713 } else {
1714 CompareFrame(
1715 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1720 const char kDescription[] =
1721 "'hello' data frame with 1 byte padding, no FIN";
1722 const unsigned char kV3FrameData[] = { // Also applies for V2.
1723 0x00, 0x00, 0x00, 0x01,
1724 0x00, 0x00, 0x00, 0x05,
1725 'h', 'e', 'l', 'l',
1729 const unsigned char kV4FrameData[] = {
1730 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1731 0x08, 0x00, 0x00, 0x00,
1732 0x01, 0x00, // Pad length field.
1733 'h', 'e', 'l', 'l', // Data
1734 'o',
1736 const char bytes[] = "hello";
1738 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1739 // The pad length field itself is used for the 1-byte padding and no padding
1740 // payload is needed.
1741 data_ir.set_padding_len(1);
1742 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1743 if (IsSpdy4()) {
1744 CompareFrame(
1745 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1746 } else {
1747 CompareFrame(
1748 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1751 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1752 CompareCharArraysWithHexError(
1753 kDescription,
1754 reinterpret_cast<const unsigned char*>(frame->data()),
1755 framer.GetDataFrameMinimumSize(),
1756 IsSpdy4() ? kV4FrameData : kV3FrameData,
1757 framer.GetDataFrameMinimumSize());
1761 const char kDescription[] = "Data frame with negative data byte, no FIN";
1762 const unsigned char kV3FrameData[] = { // Also applies for V2.
1763 0x00, 0x00, 0x00, 0x01,
1764 0x00, 0x00, 0x00, 0x01,
1765 0xff
1767 const unsigned char kV4FrameData[] = {
1768 0x00, 0x00, 0x01, 0x00, 0x00,
1769 0x00, 0x00, 0x00, 0x01,
1770 0xff
1772 SpdyDataIR data_ir(1, StringPiece("\xff", 1));
1773 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1774 if (IsSpdy4()) {
1775 CompareFrame(
1776 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1777 } else {
1778 CompareFrame(
1779 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1784 const char kDescription[] = "'hello' data frame, with FIN";
1785 const unsigned char kV3FrameData[] = { // Also applies for V2.
1786 0x00, 0x00, 0x00, 0x01,
1787 0x01, 0x00, 0x00, 0x05,
1788 'h', 'e', 'l', 'l',
1791 const unsigned char kV4FrameData[] = {
1792 0x00, 0x00, 0x05, 0x00,
1793 0x01, 0x00, 0x00, 0x00,
1794 0x01, 'h', 'e', 'l',
1795 'l', 'o'
1797 SpdyDataIR data_ir(1, StringPiece("hello", 5));
1798 data_ir.set_fin(true);
1799 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1800 if (IsSpdy4()) {
1801 CompareFrame(
1802 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1803 } else {
1804 CompareFrame(
1805 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1810 const char kDescription[] = "Empty data frame";
1811 const unsigned char kV3FrameData[] = { // Also applies for V2.
1812 0x00, 0x00, 0x00, 0x01,
1813 0x00, 0x00, 0x00, 0x00,
1815 const unsigned char kV4FrameData[] = {
1816 0x00, 0x00, 0x00, 0x00,
1817 0x00, 0x00, 0x00, 0x00,
1818 0x01,
1820 SpdyDataIR data_ir(1, StringPiece());
1821 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1822 if (IsSpdy4()) {
1823 CompareFrame(
1824 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1825 } else {
1826 CompareFrame(
1827 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1830 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1831 CompareCharArraysWithHexError(
1832 kDescription,
1833 reinterpret_cast<const unsigned char*>(frame->data()),
1834 framer.GetDataFrameMinimumSize(),
1835 IsSpdy4() ? kV4FrameData : kV3FrameData,
1836 framer.GetDataFrameMinimumSize());
1840 const char kDescription[] = "Data frame with max stream ID";
1841 const unsigned char kV3FrameData[] = { // Also applies for V2.
1842 0x7f, 0xff, 0xff, 0xff,
1843 0x01, 0x00, 0x00, 0x05,
1844 'h', 'e', 'l', 'l',
1847 const unsigned char kV4FrameData[] = {
1848 0x00, 0x00, 0x05, 0x00,
1849 0x01, 0x7f, 0xff, 0xff,
1850 0xff, 'h', 'e', 'l',
1851 'l', 'o'
1853 SpdyDataIR data_ir(0x7fffffff, "hello");
1854 data_ir.set_fin(true);
1855 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1856 if (IsSpdy4()) {
1857 CompareFrame(
1858 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1859 } else {
1860 CompareFrame(
1861 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1865 if (!IsSpdy4()) {
1866 // This test does not apply to SPDY 4 because the max frame size is smaller
1867 // than 4MB.
1868 const char kDescription[] = "Large data frame";
1869 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1870 const string kData(kDataSize, 'A');
1871 const unsigned char kFrameHeader[] = {
1872 0x00, 0x00, 0x00, 0x01,
1873 0x01, 0x40, 0x00, 0x00,
1876 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1877 scoped_ptr<unsigned char[]> expected_frame_data(
1878 new unsigned char[kFrameSize]);
1879 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1880 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1882 SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
1883 data_ir.set_fin(true);
1884 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1885 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1889 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1890 if (!IsSpdy2() && !IsSpdy3()) {
1891 // SYN_STREAM unsupported in SPDY>3
1892 return;
1894 SpdyFramer framer(spdy_version_);
1895 framer.set_enable_compression(false);
1898 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1900 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1901 const unsigned char kV2FrameData[] = {
1902 0x80, spdy_version_ch_, 0x00, 0x01,
1903 0x00, 0x00, 0x00, 0x20,
1904 0x00, 0x00, 0x00, 0x01,
1905 0x00, 0x00, 0x00, 0x00,
1906 kPri, 0x00, 0x00, 0x02,
1907 0x00, 0x03, 'b', 'a',
1908 'r', 0x00, 0x03, 'f',
1909 'o', 'o', 0x00, 0x03,
1910 'f', 'o', 'o', 0x00,
1911 0x03, 'b', 'a', 'r'
1913 const unsigned char kV3FrameData[] = {
1914 0x80, spdy_version_ch_, 0x00, 0x01,
1915 0x00, 0x00, 0x00, 0x2a,
1916 0x00, 0x00, 0x00, 0x01,
1917 0x00, 0x00, 0x00, 0x00,
1918 kPri, 0x00, 0x00, 0x00,
1919 0x00, 0x02, 0x00, 0x00,
1920 0x00, 0x03, 'b', 'a',
1921 'r', 0x00, 0x00, 0x00,
1922 0x03, 'f', 'o', 'o',
1923 0x00, 0x00, 0x00, 0x03,
1924 'f', 'o', 'o', 0x00,
1925 0x00, 0x00, 0x03, 'b',
1926 'a', 'r'
1928 SpdySynStreamIR syn_stream(1);
1929 syn_stream.set_priority(framer.GetLowestPriority());
1930 syn_stream.SetHeader("bar", "foo");
1931 syn_stream.SetHeader("foo", "bar");
1932 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1933 if (IsSpdy2()) {
1934 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1935 } else if (IsSpdy3()) {
1936 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1937 } else {
1938 LOG(FATAL) << "Unsupported version in test.";
1943 const char kDescription[] =
1944 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1945 "max stream ID";
1947 const unsigned char kV2FrameData[] = {
1948 0x80, spdy_version_ch_, 0x00, 0x01,
1949 0x01, 0x00, 0x00, 0x1D,
1950 0x7f, 0xff, 0xff, 0xff,
1951 0x7f, 0xff, 0xff, 0xff,
1952 0x00, 0x00, 0x00, 0x02,
1953 0x00, 0x00, 0x00, 0x03,
1954 'f', 'o', 'o', 0x00,
1955 0x03, 'f', 'o', 'o',
1956 0x00, 0x03, 'b', 'a',
1959 const unsigned char kV3FrameData[] = {
1960 0x80, spdy_version_ch_, 0x00, 0x01,
1961 0x01, 0x00, 0x00, 0x27,
1962 0x7f, 0xff, 0xff, 0xff,
1963 0x7f, 0xff, 0xff, 0xff,
1964 0x00, 0x00, 0x00, 0x00,
1965 0x00, 0x02, 0x00, 0x00,
1966 0x00, 0x00, 0x00, 0x00,
1967 0x00, 0x03, 'f', 'o',
1968 'o', 0x00, 0x00, 0x00,
1969 0x03, 'f', 'o', 'o',
1970 0x00, 0x00, 0x00, 0x03,
1971 'b', 'a', 'r'
1973 SpdySynStreamIR syn_stream(0x7fffffff);
1974 syn_stream.set_associated_to_stream_id(0x7fffffff);
1975 syn_stream.set_priority(framer.GetHighestPriority());
1976 syn_stream.set_fin(true);
1977 syn_stream.SetHeader("", "foo");
1978 syn_stream.SetHeader("foo", "bar");
1979 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1980 if (IsSpdy2()) {
1981 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1982 } else if (IsSpdy3()) {
1983 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1984 } else {
1985 LOG(FATAL) << "Unsupported version in test.";
1990 const char kDescription[] =
1991 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1992 "max stream ID";
1994 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
1995 const unsigned char kV2FrameData[] = {
1996 0x80, spdy_version_ch_, 0x00, 0x01,
1997 0x01, 0x00, 0x00, 0x1D,
1998 0x7f, 0xff, 0xff, 0xff,
1999 0x7f, 0xff, 0xff, 0xff,
2000 kPri, 0x00, 0x00, 0x02,
2001 0x00, 0x03, 'b', 'a',
2002 'r', 0x00, 0x03, 'f',
2003 'o', 'o', 0x00, 0x03,
2004 'f', 'o', 'o', 0x00,
2005 0x00
2007 const unsigned char kV3FrameData[] = {
2008 0x80, spdy_version_ch_, 0x00, 0x01,
2009 0x01, 0x00, 0x00, 0x27,
2010 0x7f, 0xff, 0xff, 0xff,
2011 0x7f, 0xff, 0xff, 0xff,
2012 kPri, 0x00, 0x00, 0x00,
2013 0x00, 0x02, 0x00, 0x00,
2014 0x00, 0x03, 'b', 'a',
2015 'r', 0x00, 0x00, 0x00,
2016 0x03, 'f', 'o', 'o',
2017 0x00, 0x00, 0x00, 0x03,
2018 'f', 'o', 'o', 0x00,
2019 0x00, 0x00, 0x00
2021 SpdySynStreamIR syn_stream(0x7fffffff);
2022 syn_stream.set_associated_to_stream_id(0x7fffffff);
2023 syn_stream.set_priority(1);
2024 syn_stream.set_fin(true);
2025 syn_stream.SetHeader("bar", "foo");
2026 syn_stream.SetHeader("foo", "");
2027 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2028 if (IsSpdy2()) {
2029 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2030 } else if (IsSpdy3()) {
2031 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2032 } else {
2033 LOG(FATAL) << "Unsupported version in test.";
2038 // TODO(phajdan.jr): Clean up after we no longer need
2039 // to workaround http://crbug.com/139744.
2040 #if !defined(USE_SYSTEM_ZLIB)
2041 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2042 if (!IsSpdy2() && !IsSpdy3()) {
2043 // SYN_STREAM not supported for SPDY>3
2044 return;
2046 SpdyFramer framer(spdy_version_);
2047 framer.set_enable_compression(true);
2050 const char kDescription[] =
2051 "SYN_STREAM frame, low pri, no FIN";
2053 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2054 const unsigned char kV2FrameData[] = {
2055 0x80, spdy_version_ch_, 0x00, 0x01,
2056 0x00, 0x00, 0x00, 0x36,
2057 0x00, 0x00, 0x00, 0x01,
2058 0x00, 0x00, 0x00, 0x00,
2059 0x80, 0x00, 0x38, 0xea,
2060 0xdf, 0xa2, 0x51, 0xb2,
2061 0x62, 0x60, 0x62, 0x60,
2062 0x4e, 0x4a, 0x2c, 0x62,
2063 0x60, 0x06, 0x08, 0xa0,
2064 0xb4, 0xfc, 0x7c, 0x80,
2065 0x00, 0x62, 0x60, 0x4e,
2066 0xcb, 0xcf, 0x67, 0x60,
2067 0x06, 0x08, 0xa0, 0xa4,
2068 0xc4, 0x22, 0x80, 0x00,
2069 0x02, 0x00, 0x00, 0x00,
2070 0xff, 0xff,
2072 const unsigned char kV3FrameData[] = {
2073 0x80, spdy_version_ch_, 0x00, 0x01,
2074 0x00, 0x00, 0x00, 0x37,
2075 0x00, 0x00, 0x00, 0x01,
2076 0x00, 0x00, 0x00, 0x00,
2077 0x80, 0x00, 0x38, 0xEA,
2078 0xE3, 0xC6, 0xA7, 0xC2,
2079 0x02, 0xE5, 0x0E, 0x50,
2080 0xC2, 0x4B, 0x4A, 0x04,
2081 0xE5, 0x0B, 0x66, 0x80,
2082 0x00, 0x4A, 0xCB, 0xCF,
2083 0x07, 0x08, 0x20, 0x10,
2084 0x95, 0x96, 0x9F, 0x0F,
2085 0xA2, 0x00, 0x02, 0x28,
2086 0x29, 0xB1, 0x08, 0x20,
2087 0x80, 0x00, 0x00, 0x00,
2088 0x00, 0xFF, 0xFF,
2090 SpdySynStreamIR syn_stream(1);
2091 syn_stream.set_priority(priority);
2092 syn_stream.SetHeader("bar", "foo");
2093 syn_stream.SetHeader("foo", "bar");
2094 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2095 if (IsSpdy2()) {
2096 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2097 } else if (IsSpdy3()) {
2098 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2099 } else {
2100 LOG(FATAL) << "Unsupported version in test.";
2104 #endif // !defined(USE_SYSTEM_ZLIB)
2106 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2107 if (spdy_version_ > SPDY3) {
2108 // SYN_REPLY unsupported in SPDY>3
2109 return;
2111 SpdyFramer framer(spdy_version_);
2112 framer.set_enable_compression(false);
2115 const char kDescription[] = "SYN_REPLY frame, no FIN";
2117 const unsigned char kV2FrameData[] = {
2118 0x80, spdy_version_ch_, 0x00, 0x02,
2119 0x00, 0x00, 0x00, 0x1C,
2120 0x00, 0x00, 0x00, 0x01,
2121 0x00, 0x00, 0x00, 0x02,
2122 0x00, 0x03, 'b', 'a',
2123 'r', 0x00, 0x03, 'f',
2124 'o', 'o', 0x00, 0x03,
2125 'f', 'o', 'o', 0x00,
2126 0x03, 'b', 'a', 'r'
2128 const unsigned char kV3FrameData[] = {
2129 0x80, spdy_version_ch_, 0x00, 0x02,
2130 0x00, 0x00, 0x00, 0x24,
2131 0x00, 0x00, 0x00, 0x01,
2132 0x00, 0x00, 0x00, 0x02,
2133 0x00, 0x00, 0x00, 0x03,
2134 'b', 'a', 'r', 0x00,
2135 0x00, 0x00, 0x03, 'f',
2136 'o', 'o', 0x00, 0x00,
2137 0x00, 0x03, 'f', 'o',
2138 'o', 0x00, 0x00, 0x00,
2139 0x03, 'b', 'a', 'r'
2141 SpdySynReplyIR syn_reply(1);
2142 syn_reply.SetHeader("bar", "foo");
2143 syn_reply.SetHeader("foo", "bar");
2144 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2145 if (IsSpdy2()) {
2146 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2147 } else if (IsSpdy3()) {
2148 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2149 } else {
2150 LOG(FATAL) << "Unsupported version in test.";
2155 const char kDescription[] =
2156 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2158 const unsigned char kV2FrameData[] = {
2159 0x80, spdy_version_ch_, 0x00, 0x02,
2160 0x01, 0x00, 0x00, 0x19,
2161 0x7f, 0xff, 0xff, 0xff,
2162 0x00, 0x00, 0x00, 0x02,
2163 0x00, 0x00, 0x00, 0x03,
2164 'f', 'o', 'o', 0x00,
2165 0x03, 'f', 'o', 'o',
2166 0x00, 0x03, 'b', 'a',
2169 const unsigned char kV3FrameData[] = {
2170 0x80, spdy_version_ch_, 0x00, 0x02,
2171 0x01, 0x00, 0x00, 0x21,
2172 0x7f, 0xff, 0xff, 0xff,
2173 0x00, 0x00, 0x00, 0x02,
2174 0x00, 0x00, 0x00, 0x00,
2175 0x00, 0x00, 0x00, 0x03,
2176 'f', 'o', 'o', 0x00,
2177 0x00, 0x00, 0x03, 'f',
2178 'o', 'o', 0x00, 0x00,
2179 0x00, 0x03, 'b', 'a',
2182 SpdySynReplyIR syn_reply(0x7fffffff);
2183 syn_reply.set_fin(true);
2184 syn_reply.SetHeader("", "foo");
2185 syn_reply.SetHeader("foo", "bar");
2186 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2187 if (IsSpdy2()) {
2188 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2189 } else if (IsSpdy3()) {
2190 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2191 } else {
2192 LOG(FATAL) << "Unsupported version in test.";
2197 const char kDescription[] =
2198 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2200 const unsigned char kV2FrameData[] = {
2201 0x80, spdy_version_ch_, 0x00, 0x02,
2202 0x01, 0x00, 0x00, 0x19,
2203 0x7f, 0xff, 0xff, 0xff,
2204 0x00, 0x00, 0x00, 0x02,
2205 0x00, 0x03, 'b', 'a',
2206 'r', 0x00, 0x03, 'f',
2207 'o', 'o', 0x00, 0x03,
2208 'f', 'o', 'o', 0x00,
2209 0x00
2211 const unsigned char kV3FrameData[] = {
2212 0x80, spdy_version_ch_, 0x00, 0x02,
2213 0x01, 0x00, 0x00, 0x21,
2214 0x7f, 0xff, 0xff, 0xff,
2215 0x00, 0x00, 0x00, 0x02,
2216 0x00, 0x00, 0x00, 0x03,
2217 'b', 'a', 'r', 0x00,
2218 0x00, 0x00, 0x03, 'f',
2219 'o', 'o', 0x00, 0x00,
2220 0x00, 0x03, 'f', 'o',
2221 'o', 0x00, 0x00, 0x00,
2222 0x00
2224 SpdySynReplyIR syn_reply(0x7fffffff);
2225 syn_reply.set_fin(true);
2226 syn_reply.SetHeader("bar", "foo");
2227 syn_reply.SetHeader("foo", "");
2228 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2229 if (IsSpdy2()) {
2230 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2231 } else if (IsSpdy3()) {
2232 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2233 } else {
2234 LOG(FATAL) << "Unsupported version in test.";
2239 // TODO(phajdan.jr): Clean up after we no longer need
2240 // to workaround http://crbug.com/139744.
2241 #if !defined(USE_SYSTEM_ZLIB)
2242 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2243 if (spdy_version_ > SPDY3) {
2244 // SYN_REPLY unsupported in SPDY>3
2245 return;
2247 SpdyFramer framer(spdy_version_);
2248 framer.set_enable_compression(true);
2251 const char kDescription[] = "SYN_REPLY frame, no FIN";
2253 const unsigned char kV2FrameData[] = {
2254 0x80, spdy_version_ch_, 0x00, 0x02,
2255 0x00, 0x00, 0x00, 0x32,
2256 0x00, 0x00, 0x00, 0x01,
2257 0x00, 0x00, 0x38, 0xea,
2258 0xdf, 0xa2, 0x51, 0xb2,
2259 0x62, 0x60, 0x62, 0x60,
2260 0x4e, 0x4a, 0x2c, 0x62,
2261 0x60, 0x06, 0x08, 0xa0,
2262 0xb4, 0xfc, 0x7c, 0x80,
2263 0x00, 0x62, 0x60, 0x4e,
2264 0xcb, 0xcf, 0x67, 0x60,
2265 0x06, 0x08, 0xa0, 0xa4,
2266 0xc4, 0x22, 0x80, 0x00,
2267 0x02, 0x00, 0x00, 0x00,
2268 0xff, 0xff,
2270 const unsigned char kV3FrameData[] = {
2271 0x80, spdy_version_ch_, 0x00, 0x02,
2272 0x00, 0x00, 0x00, 0x31,
2273 0x00, 0x00, 0x00, 0x01,
2274 0x38, 0xea, 0xe3, 0xc6,
2275 0xa7, 0xc2, 0x02, 0xe5,
2276 0x0e, 0x50, 0xc2, 0x4b,
2277 0x4a, 0x04, 0xe5, 0x0b,
2278 0x66, 0x80, 0x00, 0x4a,
2279 0xcb, 0xcf, 0x07, 0x08,
2280 0x20, 0x10, 0x95, 0x96,
2281 0x9f, 0x0f, 0xa2, 0x00,
2282 0x02, 0x28, 0x29, 0xb1,
2283 0x08, 0x20, 0x80, 0x00,
2284 0x00, 0x00, 0x00, 0xff,
2285 0xff,
2287 SpdySynReplyIR syn_reply(1);
2288 syn_reply.SetHeader("bar", "foo");
2289 syn_reply.SetHeader("foo", "bar");
2290 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2291 if (IsSpdy2()) {
2292 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2293 } else if (IsSpdy3()) {
2294 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2295 } else {
2296 LOG(FATAL) << "Unsupported version in test.";
2300 #endif // !defined(USE_SYSTEM_ZLIB)
2302 TEST_P(SpdyFramerTest, CreateRstStream) {
2303 SpdyFramer framer(spdy_version_);
2306 const char kDescription[] = "RST_STREAM frame";
2307 const unsigned char kV3FrameData[] = { // Also applies for V2.
2308 0x80, spdy_version_ch_, 0x00, 0x03,
2309 0x00, 0x00, 0x00, 0x08,
2310 0x00, 0x00, 0x00, 0x01,
2311 0x00, 0x00, 0x00, 0x01,
2313 const unsigned char kV4FrameData[] = {
2314 0x00, 0x00, 0x07, 0x03,
2315 0x00, 0x00, 0x00, 0x00,
2316 0x01, 0x00, 0x00, 0x00,
2317 0x01, 0x52, 0x53, 0x54
2319 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2320 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2321 if (IsSpdy4()) {
2322 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2323 } else {
2324 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2329 const char kDescription[] = "RST_STREAM frame with max stream ID";
2330 const unsigned char kV3FrameData[] = { // Also applies for V2.
2331 0x80, spdy_version_ch_, 0x00, 0x03,
2332 0x00, 0x00, 0x00, 0x08,
2333 0x7f, 0xff, 0xff, 0xff,
2334 0x00, 0x00, 0x00, 0x01,
2336 const unsigned char kV4FrameData[] = {
2337 0x00, 0x00, 0x04, 0x03,
2338 0x00, 0x7f, 0xff, 0xff,
2339 0xff, 0x00, 0x00, 0x00,
2340 0x01,
2342 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2343 RST_STREAM_PROTOCOL_ERROR,
2344 "");
2345 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2346 if (IsSpdy4()) {
2347 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2348 } else {
2349 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2354 const char kDescription[] = "RST_STREAM frame with max status code";
2355 const unsigned char kV3FrameData[] = { // Also applies for V2.
2356 0x80, spdy_version_ch_, 0x00, 0x03,
2357 0x00, 0x00, 0x00, 0x08,
2358 0x7f, 0xff, 0xff, 0xff,
2359 0x00, 0x00, 0x00, 0x06,
2361 const unsigned char kV4FrameData[] = {
2362 0x00, 0x00, 0x04, 0x03,
2363 0x00, 0x7f, 0xff, 0xff,
2364 0xff, 0x00, 0x00, 0x00,
2365 0x06,
2367 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2368 RST_STREAM_INTERNAL_ERROR,
2369 "");
2370 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2371 if (IsSpdy4()) {
2372 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2373 } else {
2374 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2379 TEST_P(SpdyFramerTest, CreateSettings) {
2380 SpdyFramer framer(spdy_version_);
2383 const char kDescription[] = "Network byte order SETTINGS frame";
2385 const unsigned char kV2FrameData[] = {
2386 0x80, spdy_version_ch_, 0x00, 0x04,
2387 0x00, 0x00, 0x00, 0x0c,
2388 0x00, 0x00, 0x00, 0x01,
2389 0x07, 0x00, 0x00, 0x01,
2390 0x0a, 0x0b, 0x0c, 0x0d,
2392 const unsigned char kV3FrameData[] = {
2393 0x80, spdy_version_ch_, 0x00, 0x04,
2394 0x00, 0x00, 0x00, 0x0c,
2395 0x00, 0x00, 0x00, 0x01,
2396 0x01, 0x00, 0x00, 0x07,
2397 0x0a, 0x0b, 0x0c, 0x0d,
2399 const unsigned char kV4FrameData[] = {
2400 0x00, 0x00, 0x06, 0x04,
2401 0x00, 0x00, 0x00, 0x00,
2402 0x00, 0x00, 0x04, 0x0a,
2403 0x0b, 0x0c, 0x0d,
2406 uint32 kValue = 0x0a0b0c0d;
2407 SpdySettingsIR settings_ir;
2409 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2410 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2411 SettingsMap settings;
2412 settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
2413 EXPECT_EQ(kFlags, settings[kId].first);
2414 EXPECT_EQ(kValue, settings[kId].second);
2415 settings_ir.AddSetting(kId,
2416 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2417 kFlags & SETTINGS_FLAG_PERSISTED,
2418 kValue);
2420 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2421 if (IsSpdy2()) {
2422 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2423 } else if (IsSpdy3()) {
2424 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2425 } else {
2426 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2431 const char kDescription[] = "Basic SETTINGS frame";
2433 const unsigned char kV2FrameData[] = {
2434 0x80, spdy_version_ch_, 0x00, 0x04,
2435 0x00, 0x00, 0x00, 0x24,
2436 0x00, 0x00, 0x00, 0x04,
2437 0x01, 0x00, 0x00, 0x00, // 1st Setting
2438 0x00, 0x00, 0x00, 0x05,
2439 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2440 0x00, 0x00, 0x00, 0x06,
2441 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2442 0x00, 0x00, 0x00, 0x07,
2443 0x04, 0x00, 0x00, 0x00, // 4th Setting
2444 0x00, 0x00, 0x00, 0x08,
2446 const unsigned char kV3FrameData[] = {
2447 0x80, spdy_version_ch_, 0x00, 0x04,
2448 0x00, 0x00, 0x00, 0x24,
2449 0x00, 0x00, 0x00, 0x04,
2450 0x00, 0x00, 0x00, 0x01, // 1st Setting
2451 0x00, 0x00, 0x00, 0x05,
2452 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2453 0x00, 0x00, 0x00, 0x06,
2454 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2455 0x00, 0x00, 0x00, 0x07,
2456 0x00, 0x00, 0x00, 0x04, // 4th Setting
2457 0x00, 0x00, 0x00, 0x08,
2459 // These end up seemingly out of order because of the way that our internal
2460 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2461 // the wire.
2462 const unsigned char kV4FrameData[] = {
2463 0x00, 0x00, 0x18, 0x04,
2464 0x00, 0x00, 0x00, 0x00,
2465 0x00, 0x00, 0x03, // 3rd Setting
2466 0x00, 0x00, 0x00, 0x07,
2467 0x00, 0x04, // 4th Setting
2468 0x00, 0x00, 0x00, 0x08,
2469 0x00, 0x01, // 1st Setting
2470 0x00, 0x00, 0x00, 0x05,
2471 0x00, 0x02, // 2nd Setting
2472 0x00, 0x00, 0x00, 0x06,
2475 SpdySettingsIR settings_ir;
2476 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2477 false, // persist
2478 false, // persisted
2480 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2481 false, // persist
2482 false, // persisted
2484 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2485 false, // persist
2486 false, // persisted
2488 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2489 false, // persist
2490 false, // persisted
2492 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2494 if (IsSpdy2()) {
2495 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2496 } else if (IsSpdy3()) {
2497 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2498 } else {
2499 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2504 const char kDescription[] = "Empty SETTINGS frame";
2506 const unsigned char kV3FrameData[] = { // Also applies for V2.
2507 0x80, spdy_version_ch_, 0x00, 0x04,
2508 0x00, 0x00, 0x00, 0x04,
2509 0x00, 0x00, 0x00, 0x00,
2511 const unsigned char kV4FrameData[] = {
2512 0x00, 0x00, 0x00, 0x04,
2513 0x00, 0x00, 0x00, 0x00,
2514 0x00,
2516 SpdySettingsIR settings_ir;
2517 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2518 if (IsSpdy4()) {
2519 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2520 } else {
2521 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2526 TEST_P(SpdyFramerTest, CreatePingFrame) {
2527 SpdyFramer framer(spdy_version_);
2530 const char kDescription[] = "PING frame";
2531 const unsigned char kV3FrameData[] = { // Also applies for V2.
2532 0x80, spdy_version_ch_, 0x00, 0x06,
2533 0x00, 0x00, 0x00, 0x04,
2534 0x12, 0x34, 0x56, 0x78,
2536 const unsigned char kV4FrameData[] = {
2537 0x00, 0x00, 0x08, 0x06,
2538 0x00, 0x00, 0x00, 0x00,
2539 0x00, 0x12, 0x34, 0x56,
2540 0x78, 0x9a, 0xbc, 0xde,
2541 0xff,
2543 const unsigned char kV4FrameDataWithAck[] = {
2544 0x00, 0x00, 0x08, 0x06,
2545 0x01, 0x00, 0x00, 0x00,
2546 0x00, 0x12, 0x34, 0x56,
2547 0x78, 0x9a, 0xbc, 0xde,
2548 0xff,
2550 scoped_ptr<SpdyFrame> frame;
2551 if (IsSpdy4()) {
2552 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2553 SpdyPingIR ping_ir(kPingId);
2554 // Tests SpdyPingIR when the ping is not an ack.
2555 ASSERT_FALSE(ping_ir.is_ack());
2556 frame.reset(framer.SerializePing(ping_ir));
2557 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2559 // Tests SpdyPingIR when the ping is an ack.
2560 ping_ir.set_is_ack(true);
2561 frame.reset(framer.SerializePing(ping_ir));
2562 CompareFrame(kDescription, *frame,
2563 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2565 } else {
2566 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2567 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2572 TEST_P(SpdyFramerTest, CreateGoAway) {
2573 SpdyFramer framer(spdy_version_);
2576 const char kDescription[] = "GOAWAY frame";
2577 const unsigned char kV2FrameData[] = {
2578 0x80, spdy_version_ch_, 0x00, 0x07,
2579 0x00, 0x00, 0x00, 0x04,
2580 0x00, 0x00, 0x00, 0x00, // Stream Id
2582 const unsigned char kV3FrameData[] = {
2583 0x80, spdy_version_ch_, 0x00, 0x07,
2584 0x00, 0x00, 0x00, 0x08,
2585 0x00, 0x00, 0x00, 0x00, // Stream Id
2586 0x00, 0x00, 0x00, 0x00, // Status
2588 const unsigned char kV4FrameData[] = {
2589 0x00, 0x00, 0x0a, 0x07,
2590 0x00, 0x00, 0x00, 0x00,
2591 0x00, 0x00, 0x00, 0x00, // Stream id
2592 0x00, 0x00, 0x00, 0x00, // Status
2593 0x00, 0x47, 0x41, // Opaque Description
2595 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2596 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2597 if (IsSpdy2()) {
2598 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2599 } else if (IsSpdy3()) {
2600 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2601 } else {
2602 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2607 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2608 const unsigned char kV2FrameData[] = {
2609 0x80, spdy_version_ch_, 0x00, 0x07,
2610 0x00, 0x00, 0x00, 0x04,
2611 0x7f, 0xff, 0xff, 0xff, // Stream Id
2613 const unsigned char kV3FrameData[] = {
2614 0x80, spdy_version_ch_, 0x00, 0x07,
2615 0x00, 0x00, 0x00, 0x08,
2616 0x7f, 0xff, 0xff, 0xff, // Stream Id
2617 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2619 const unsigned char kV4FrameData[] = {
2620 0x00, 0x00, 0x0a, 0x07,
2621 0x00, 0x00, 0x00, 0x00,
2622 0x00, 0x7f, 0xff, 0xff, // Stream Id
2623 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2624 0x02, 0x47, 0x41, // Opaque Description
2626 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2627 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2628 if (IsSpdy2()) {
2629 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2630 } else if (IsSpdy3()) {
2631 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2632 } else {
2633 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2638 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2639 SpdyFramer framer(spdy_version_);
2640 framer.set_enable_compression(false);
2643 const char kDescription[] = "HEADERS frame, no FIN";
2645 const unsigned char kV2FrameData[] = {
2646 0x80, spdy_version_ch_, 0x00, 0x08,
2647 0x00, 0x00, 0x00, 0x1C,
2648 0x00, 0x00, 0x00, 0x01,
2649 0x00, 0x00, 0x00, 0x02,
2650 0x00, 0x03, 'b', 'a',
2651 'r', 0x00, 0x03, 'f',
2652 'o', 'o', 0x00, 0x03,
2653 'f', 'o', 'o', 0x00,
2654 0x03, 'b', 'a', 'r'
2656 const unsigned char kV3FrameData[] = {
2657 0x80, spdy_version_ch_, 0x00, 0x08,
2658 0x00, 0x00, 0x00, 0x24,
2659 0x00, 0x00, 0x00, 0x01,
2660 0x00, 0x00, 0x00, 0x02,
2661 0x00, 0x00, 0x00, 0x03,
2662 'b', 'a', 'r', 0x00,
2663 0x00, 0x00, 0x03, 'f',
2664 'o', 'o', 0x00, 0x00,
2665 0x00, 0x03, 'f', 'o',
2666 'o', 0x00, 0x00, 0x00,
2667 0x03, 'b', 'a', 'r'
2669 const unsigned char kV4FrameData[] = {
2670 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2671 0x04, 0x00, 0x00, 0x00, // Stream 1
2672 0x01, 0x00, 0x03, 0x62, // @.ba
2673 0x61, 0x72, 0x03, 0x66, // r.fo
2674 0x6f, 0x6f, 0x00, 0x03, // o@.f
2675 0x66, 0x6f, 0x6f, 0x03, // oo.b
2676 0x62, 0x61, 0x72, // ar
2678 SpdyHeadersIR headers_ir(1);
2679 headers_ir.SetHeader("bar", "foo");
2680 headers_ir.SetHeader("foo", "bar");
2681 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2682 if (IsSpdy2()) {
2683 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2684 } else if (IsSpdy3()) {
2685 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2686 } else {
2687 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2692 const char kDescription[] =
2693 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2695 const unsigned char kV2FrameData[] = {
2696 0x80, spdy_version_ch_, 0x00, 0x08,
2697 0x01, 0x00, 0x00, 0x19,
2698 0x7f, 0xff, 0xff, 0xff,
2699 0x00, 0x00, 0x00, 0x02,
2700 0x00, 0x00, 0x00, 0x03,
2701 'f', 'o', 'o', 0x00,
2702 0x03, 'f', 'o', 'o',
2703 0x00, 0x03, 'b', 'a',
2706 const unsigned char kV3FrameData[] = {
2707 0x80, spdy_version_ch_, 0x00, 0x08,
2708 0x01, 0x00, 0x00, 0x21,
2709 0x7f, 0xff, 0xff, 0xff,
2710 0x00, 0x00, 0x00, 0x02,
2711 0x00, 0x00, 0x00, 0x00,
2712 0x00, 0x00, 0x00, 0x03,
2713 'f', 'o', 'o', 0x00,
2714 0x00, 0x00, 0x03, 'f',
2715 'o', 'o', 0x00, 0x00,
2716 0x00, 0x03, 'b', 'a',
2719 const unsigned char kV4FrameData[] = {
2720 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2721 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2722 0xff, 0x00, 0x00, 0x03, // @..
2723 0x66, 0x6f, 0x6f, 0x00, // foo@
2724 0x03, 0x66, 0x6f, 0x6f, // .foo
2725 0x03, 0x62, 0x61, 0x72, // .bar
2727 SpdyHeadersIR headers_ir(0x7fffffff);
2728 headers_ir.set_fin(true);
2729 headers_ir.SetHeader("", "foo");
2730 headers_ir.SetHeader("foo", "bar");
2731 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2732 if (IsSpdy2()) {
2733 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2734 } else if (IsSpdy3()) {
2735 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2736 } else {
2737 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2742 const char kDescription[] =
2743 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2745 const unsigned char kV2FrameData[] = {
2746 0x80, spdy_version_ch_, 0x00, 0x08,
2747 0x01, 0x00, 0x00, 0x19,
2748 0x7f, 0xff, 0xff, 0xff,
2749 0x00, 0x00, 0x00, 0x02,
2750 0x00, 0x03, 'b', 'a',
2751 'r', 0x00, 0x03, 'f',
2752 'o', 'o', 0x00, 0x03,
2753 'f', 'o', 'o', 0x00,
2754 0x00
2756 const unsigned char kV3FrameData[] = {
2757 0x80, spdy_version_ch_, 0x00, 0x08,
2758 0x01, 0x00, 0x00, 0x21,
2759 0x7f, 0xff, 0xff, 0xff,
2760 0x00, 0x00, 0x00, 0x02,
2761 0x00, 0x00, 0x00, 0x03,
2762 'b', 'a', 'r', 0x00,
2763 0x00, 0x00, 0x03, 'f',
2764 'o', 'o', 0x00, 0x00,
2765 0x00, 0x03, 'f', 'o',
2766 'o', 0x00, 0x00, 0x00,
2767 0x00
2769 const unsigned char kV4FrameData[] = {
2770 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2771 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2772 0xff, 0x00, 0x03, 0x62, // @.b
2773 0x61, 0x72, 0x03, 0x66, // ar.f
2774 0x6f, 0x6f, 0x00, 0x03, // oo@.
2775 0x66, 0x6f, 0x6f, 0x00, // foo.
2777 SpdyHeadersIR headers_ir(0x7fffffff);
2778 headers_ir.set_fin(true);
2779 headers_ir.SetHeader("bar", "foo");
2780 headers_ir.SetHeader("foo", "");
2781 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2782 if (IsSpdy2()) {
2783 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2784 } else if (IsSpdy3()) {
2785 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2786 } else {
2787 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2792 const char kDescription[] =
2793 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2795 const unsigned char kV4FrameData[] = {
2796 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2797 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2798 0xff, 0x00, 0x00, 0x00, // parent stream
2799 0x00, 0xdb, // weight
2800 0x00, 0x03, 0x62, 0x61, // @.ba
2801 0x72, 0x03, 0x66, 0x6f, // r.fo
2802 0x6f, 0x00, 0x03, 0x66, // o@.f
2803 0x6f, 0x6f, 0x00, // oo.
2805 SpdyHeadersIR headers_ir(0x7fffffff);
2806 headers_ir.set_fin(true);
2807 headers_ir.set_priority(1);
2808 headers_ir.set_has_priority(true);
2809 headers_ir.SetHeader("bar", "foo");
2810 headers_ir.SetHeader("foo", "");
2811 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2812 if (IsSpdy2() || IsSpdy3()) {
2813 // HEADERS with priority not supported.
2814 } else {
2815 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2820 // TODO(phajdan.jr): Clean up after we no longer need
2821 // to workaround http://crbug.com/139744.
2822 #if !defined(USE_SYSTEM_ZLIB)
2823 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2824 SpdyFramer framer(spdy_version_);
2825 framer.set_enable_compression(true);
2828 const char kDescription[] = "HEADERS frame, no FIN";
2830 const unsigned char kV2FrameData[] = {
2831 0x80, spdy_version_ch_, 0x00, 0x08,
2832 0x00, 0x00, 0x00, 0x32,
2833 0x00, 0x00, 0x00, 0x01,
2834 0x00, 0x00, 0x38, 0xea,
2835 0xdf, 0xa2, 0x51, 0xb2,
2836 0x62, 0x60, 0x62, 0x60,
2837 0x4e, 0x4a, 0x2c, 0x62,
2838 0x60, 0x06, 0x08, 0xa0,
2839 0xb4, 0xfc, 0x7c, 0x80,
2840 0x00, 0x62, 0x60, 0x4e,
2841 0xcb, 0xcf, 0x67, 0x60,
2842 0x06, 0x08, 0xa0, 0xa4,
2843 0xc4, 0x22, 0x80, 0x00,
2844 0x02, 0x00, 0x00, 0x00,
2845 0xff, 0xff,
2847 const unsigned char kV3FrameData[] = {
2848 0x80, spdy_version_ch_, 0x00, 0x08,
2849 0x00, 0x00, 0x00, 0x31,
2850 0x00, 0x00, 0x00, 0x01,
2851 0x38, 0xea, 0xe3, 0xc6,
2852 0xa7, 0xc2, 0x02, 0xe5,
2853 0x0e, 0x50, 0xc2, 0x4b,
2854 0x4a, 0x04, 0xe5, 0x0b,
2855 0x66, 0x80, 0x00, 0x4a,
2856 0xcb, 0xcf, 0x07, 0x08,
2857 0x20, 0x10, 0x95, 0x96,
2858 0x9f, 0x0f, 0xa2, 0x00,
2859 0x02, 0x28, 0x29, 0xb1,
2860 0x08, 0x20, 0x80, 0x00,
2861 0x00, 0x00, 0x00, 0xff,
2862 0xff,
2864 SpdyHeadersIR headers_ir(1);
2865 headers_ir.SetHeader("bar", "foo");
2866 headers_ir.SetHeader("foo", "bar");
2867 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2868 if (IsSpdy2()) {
2869 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2870 } else if (IsSpdy3()) {
2871 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2872 } else {
2873 // Deflate compression doesn't apply to HPACK.
2877 #endif // !defined(USE_SYSTEM_ZLIB)
2879 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
2880 SpdyFramer framer(spdy_version_);
2883 const char kDescription[] = "WINDOW_UPDATE frame";
2884 const unsigned char kV3FrameData[] = { // Also applies for V2.
2885 0x80, spdy_version_ch_, 0x00, 0x09,
2886 0x00, 0x00, 0x00, 0x08,
2887 0x00, 0x00, 0x00, 0x01,
2888 0x00, 0x00, 0x00, 0x01,
2890 const unsigned char kV4FrameData[] = {
2891 0x00, 0x00, 0x04, 0x08,
2892 0x00, 0x00, 0x00, 0x00,
2893 0x01, 0x00, 0x00, 0x00,
2894 0x01,
2896 scoped_ptr<SpdyFrame> frame(
2897 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
2898 if (IsSpdy4()) {
2899 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2900 } else {
2901 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2906 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
2907 const unsigned char kV3FrameData[] = { // Also applies for V2.
2908 0x80, spdy_version_ch_, 0x00, 0x09,
2909 0x00, 0x00, 0x00, 0x08,
2910 0x7f, 0xff, 0xff, 0xff,
2911 0x00, 0x00, 0x00, 0x01,
2913 const unsigned char kV4FrameData[] = {
2914 0x00, 0x00, 0x04, 0x08,
2915 0x00, 0x7f, 0xff, 0xff,
2916 0xff, 0x00, 0x00, 0x00,
2917 0x01,
2919 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2920 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2921 if (IsSpdy4()) {
2922 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2923 } else {
2924 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2929 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
2930 const unsigned char kV3FrameData[] = { // Also applies for V2.
2931 0x80, spdy_version_ch_, 0x00, 0x09,
2932 0x00, 0x00, 0x00, 0x08,
2933 0x00, 0x00, 0x00, 0x01,
2934 0x7f, 0xff, 0xff, 0xff,
2936 const unsigned char kV4FrameData[] = {
2937 0x00, 0x00, 0x04, 0x08,
2938 0x00, 0x00, 0x00, 0x00,
2939 0x01, 0x7f, 0xff, 0xff,
2940 0xff,
2942 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
2943 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2944 if (IsSpdy4()) {
2945 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2946 } else {
2947 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2952 TEST_P(SpdyFramerTest, SerializeBlocked) {
2953 if (spdy_version_ <= SPDY3) {
2954 return;
2957 SpdyFramer framer(spdy_version_);
2959 const char kDescription[] = "BLOCKED frame";
2960 const unsigned char kType = static_cast<unsigned char>(
2961 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
2962 const unsigned char kFrameData[] = {
2963 0x00, 0x00, 0x00, kType, 0x00,
2964 0x00, 0x00, 0x00, 0x00,
2966 SpdyBlockedIR blocked_ir(0);
2967 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
2968 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
2971 TEST_P(SpdyFramerTest, CreateBlocked) {
2972 if (spdy_version_ <= SPDY3) {
2973 return;
2976 SpdyFramer framer(spdy_version_);
2978 const char kDescription[] = "BLOCKED frame";
2979 const SpdyStreamId kStreamId = 3;
2981 scoped_ptr<SpdySerializedFrame> frame_serialized(
2982 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
2983 SpdyBlockedIR blocked_ir(kStreamId);
2984 scoped_ptr<SpdySerializedFrame> frame_created(
2985 framer.SerializeFrame(blocked_ir));
2987 CompareFrames(kDescription, *frame_serialized, *frame_created);
2990 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
2991 if (spdy_version_ <= SPDY3) {
2992 return;
2995 SpdyFramer framer(spdy_version_);
2996 framer.set_enable_compression(false);
2997 const char kDescription[] = "PUSH_PROMISE frame";
2999 const unsigned char kFrameData[] = {
3000 0x00, 0x00, 0x16, 0x05, 0x04, // PUSH_PROMISE: END_HEADERS
3001 0x00, 0x00, 0x00, 0x2a, // Stream 42
3002 0x00, 0x00, 0x00, 0x39, // Promised stream 57
3003 0x00, 0x03, 0x62, 0x61, // @.ba
3004 0x72, 0x03, 0x66, 0x6f, // r.fo
3005 0x6f, 0x00, 0x03, 0x66, // o@.f
3006 0x6f, 0x6f, 0x03, 0x62, // oo.b
3007 0x61, 0x72, // ar
3010 SpdyPushPromiseIR push_promise(42, 57);
3011 push_promise.SetHeader("bar", "foo");
3012 push_promise.SetHeader("foo", "bar");
3013 scoped_ptr<SpdySerializedFrame> frame(
3014 framer.SerializePushPromise(push_promise));
3015 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3018 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3019 if (spdy_version_ <= SPDY3) {
3020 return;
3023 SpdyFramer framer(spdy_version_);
3024 framer.set_enable_compression(false);
3025 const char kDescription[] = "CONTINUATION frame";
3027 const unsigned char kFrameData[] = {
3028 0x00, 0x00, 0x12, 0x09, 0x00, // CONTINUATION
3029 0x00, 0x00, 0x00, 0x2a, // Stream 42
3030 0x00, 0x03, 0x62, 0x61, // @.ba
3031 0x72, 0x03, 0x66, 0x6f, // r.fo
3032 0x6f, 0x00, 0x03, 0x66, // o@.f
3033 0x6f, 0x6f, 0x03, 0x62, // oo.b
3034 0x61, 0x72, // ar
3037 SpdyContinuationIR continuation(42);
3038 continuation.SetHeader("bar", "foo");
3039 continuation.SetHeader("foo", "bar");
3040 scoped_ptr<SpdySerializedFrame> frame(
3041 framer.SerializeContinuation(continuation));
3042 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3045 TEST_P(SpdyFramerTest, CreateAltSvc) {
3046 if (spdy_version_ <= SPDY3) {
3047 return;
3050 SpdyFramer framer(spdy_version_);
3052 const char kDescription[] = "ALTSVC frame";
3053 const unsigned char kType = static_cast<unsigned char>(
3054 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3055 const unsigned char kFrameData[] = {
3056 0x00, 0x00, 0x17, kType, 0x00,
3057 0x00, 0x00, 0x00, 0x03,
3058 0x00, 0x00, 0x00, 0x05,
3059 0x01, 0xbb, 0x00, 0x04, // Port = 443
3060 'p', 'i', 'd', '1', // Protocol-ID
3061 0x04, 'h', 'o', 's',
3062 't', 'o', 'r', 'i',
3063 'g', 'i', 'n',
3065 SpdyAltSvcIR altsvc_ir(3);
3066 altsvc_ir.set_max_age(5);
3067 altsvc_ir.set_port(443);
3068 altsvc_ir.set_protocol_id("pid1");
3069 altsvc_ir.set_host("host");
3070 altsvc_ir.set_origin("origin");
3071 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3072 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3075 TEST_P(SpdyFramerTest, CreatePriority) {
3076 if (spdy_version_ <= SPDY3) {
3077 return;
3080 SpdyFramer framer(spdy_version_);
3082 const char kDescription[] = "PRIORITY frame";
3083 const unsigned char kType = static_cast<unsigned char>(
3084 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3085 const unsigned char kFrameData[] = {
3086 0x00, 0x00, 0x05, kType, 0x00,
3087 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3088 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3089 0x10, // Weight = 16
3091 SpdyPriorityIR priority_ir(2, 1, 16, true);
3092 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3093 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3096 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3097 if (spdy_version_ > SPDY3) {
3098 // SYN_STREAM not supported in SPDY>3
3099 return;
3101 SpdyFramer framer(spdy_version_);
3102 SpdySynStreamIR syn_stream(1);
3103 syn_stream.set_priority(1);
3104 syn_stream.SetHeader("aa", "vv");
3105 syn_stream.SetHeader("bb", "ww");
3106 SpdyHeaderBlock headers = syn_stream.name_value_block();
3107 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3108 EXPECT_TRUE(control_frame.get() != NULL);
3109 TestSpdyVisitor visitor(spdy_version_);
3110 visitor.use_compression_ = true;
3111 visitor.SimulateInFramer(
3112 reinterpret_cast<unsigned char*>(control_frame->data()),
3113 control_frame->size());
3114 EXPECT_EQ(1, visitor.syn_frame_count_);
3115 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3118 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3119 if (spdy_version_ > SPDY3) {
3120 return;
3122 SpdyFramer framer(spdy_version_);
3123 SpdySynReplyIR syn_reply(1);
3124 syn_reply.SetHeader("alpha", "beta");
3125 syn_reply.SetHeader("gamma", "delta");
3126 SpdyHeaderBlock headers = syn_reply.name_value_block();
3127 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3128 EXPECT_TRUE(control_frame.get() != NULL);
3129 TestSpdyVisitor visitor(spdy_version_);
3130 visitor.use_compression_ = true;
3131 visitor.SimulateInFramer(
3132 reinterpret_cast<unsigned char*>(control_frame->data()),
3133 control_frame->size());
3134 if (IsSpdy4()) {
3135 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3136 EXPECT_EQ(1, visitor.headers_frame_count_);
3137 } else {
3138 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3139 EXPECT_EQ(0, visitor.headers_frame_count_);
3141 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3144 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3145 SpdyFramer framer(spdy_version_);
3146 SpdyHeadersIR headers_ir(1);
3147 headers_ir.SetHeader("alpha", "beta");
3148 headers_ir.SetHeader("gamma", "delta");
3149 SpdyHeaderBlock headers = headers_ir.name_value_block();
3150 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3151 EXPECT_TRUE(control_frame.get() != NULL);
3152 TestSpdyVisitor visitor(spdy_version_);
3153 visitor.use_compression_ = true;
3154 visitor.SimulateInFramer(
3155 reinterpret_cast<unsigned char*>(control_frame->data()),
3156 control_frame->size());
3157 EXPECT_EQ(1, visitor.headers_frame_count_);
3158 // control_frame_header_data_count_ depends on the random sequence
3159 // produced by rand(), so adding, removing or running single tests
3160 // alters this value. The best we can do is assert that it happens
3161 // at least twice.
3162 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3163 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3164 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3165 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3168 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3169 SpdyFramer framer(spdy_version_);
3170 SpdyHeadersIR headers_ir(1);
3171 headers_ir.set_fin(true);
3172 headers_ir.SetHeader("alpha", "beta");
3173 headers_ir.SetHeader("gamma", "delta");
3174 SpdyHeaderBlock headers = headers_ir.name_value_block();
3175 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3176 EXPECT_TRUE(control_frame.get() != NULL);
3177 TestSpdyVisitor visitor(spdy_version_);
3178 visitor.use_compression_ = true;
3179 visitor.SimulateInFramer(
3180 reinterpret_cast<unsigned char*>(control_frame->data()),
3181 control_frame->size());
3182 EXPECT_EQ(1, visitor.headers_frame_count_);
3183 // control_frame_header_data_count_ depends on the random sequence
3184 // produced by rand(), so adding, removing or running single tests
3185 // alters this value. The best we can do is assert that it happens
3186 // at least twice.
3187 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3188 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3189 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3190 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3193 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3194 if (spdy_version_ > SPDY3) {
3195 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3196 return;
3198 // First find the size of the header value in order to just reach the control
3199 // frame max size.
3200 SpdyFramer framer(spdy_version_);
3201 framer.set_enable_compression(false);
3202 SpdySynStreamIR syn_stream(1);
3203 syn_stream.set_priority(1);
3204 syn_stream.SetHeader("aa", "");
3205 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3206 const size_t kBigValueSize =
3207 framer.GetControlFrameBufferMaxSize() - control_frame->size();
3209 // Create a frame at exactly that size.
3210 string big_value(kBigValueSize, 'x');
3211 syn_stream.SetHeader("aa", big_value);
3212 control_frame.reset(framer.SerializeSynStream(syn_stream));
3213 EXPECT_TRUE(control_frame.get() != NULL);
3214 EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size());
3216 TestSpdyVisitor visitor(spdy_version_);
3217 visitor.SimulateInFramer(
3218 reinterpret_cast<unsigned char*>(control_frame->data()),
3219 control_frame->size());
3220 EXPECT_TRUE(visitor.header_buffer_valid_);
3221 EXPECT_EQ(0, visitor.error_count_);
3222 EXPECT_EQ(1, visitor.syn_frame_count_);
3223 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3224 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3225 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3228 TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
3229 if (spdy_version_ > SPDY3) {
3230 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3231 return;
3233 // First find the size of the header value in order to just reach the control
3234 // frame max size.
3235 SpdyFramer framer(spdy_version_);
3236 framer.set_enable_compression(false);
3237 SpdySynStreamIR syn_stream(1);
3238 syn_stream.SetHeader("aa", "");
3239 syn_stream.set_priority(1);
3240 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3241 const size_t kBigValueSize =
3242 framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1;
3244 // Create a frame at exatly that size.
3245 string big_value(kBigValueSize, 'x');
3246 syn_stream.SetHeader("aa", big_value);
3247 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3248 // neither support that in Chromium, nor do we use the same DFATAL (see
3249 // SpdyFrameBuilder::WriteFramePrefix()).
3250 control_frame.reset(framer.SerializeSynStream(syn_stream));
3252 EXPECT_TRUE(control_frame.get() != NULL);
3253 EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1,
3254 control_frame->size());
3256 TestSpdyVisitor visitor(spdy_version_);
3257 visitor.SimulateInFramer(
3258 reinterpret_cast<unsigned char*>(control_frame->data()),
3259 control_frame->size());
3260 EXPECT_FALSE(visitor.header_buffer_valid_);
3261 EXPECT_EQ(1, visitor.error_count_);
3262 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3263 visitor.framer_.error_code())
3264 << SpdyFramer::ErrorCodeToString(framer.error_code());
3265 EXPECT_EQ(0, visitor.syn_frame_count_);
3266 EXPECT_EQ(0u, visitor.header_buffer_length_);
3269 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3270 if (spdy_version_ <= SPDY3) {
3271 return;
3273 SpdyFramer framer(spdy_version_);
3274 framer.set_enable_compression(false);
3275 SpdyHeadersIR headers(1);
3277 // Exact payload length will change with HPACK, but this should be long
3278 // enough to cause an overflow.
3279 const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize();
3280 string big_value(kBigValueSize, 'x');
3281 headers.SetHeader("aa", big_value);
3282 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3283 EXPECT_TRUE(control_frame.get() != NULL);
3284 EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize());
3286 TestSpdyVisitor visitor(spdy_version_);
3287 visitor.SimulateInFramer(
3288 reinterpret_cast<unsigned char*>(control_frame->data()),
3289 control_frame->size());
3290 EXPECT_TRUE(visitor.header_buffer_valid_);
3291 EXPECT_EQ(0, visitor.error_count_);
3292 EXPECT_EQ(1, visitor.headers_frame_count_);
3293 EXPECT_EQ(16, visitor.continuation_count_);
3294 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3297 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3298 if (spdy_version_ <= SPDY3) {
3299 return;
3301 SpdyFramer framer(spdy_version_);
3302 framer.set_enable_compression(false);
3303 SpdyPushPromiseIR push_promise(1, 2);
3305 // Exact payload length will change with HPACK, but this should be long
3306 // enough to cause an overflow.
3307 const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize();
3308 string big_value(kBigValueSize, 'x');
3309 push_promise.SetHeader("aa", big_value);
3310 scoped_ptr<SpdyFrame> control_frame(
3311 framer.SerializePushPromise(push_promise));
3312 EXPECT_TRUE(control_frame.get() != NULL);
3313 EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize());
3315 TestSpdyVisitor visitor(spdy_version_);
3316 visitor.SimulateInFramer(
3317 reinterpret_cast<unsigned char*>(control_frame->data()),
3318 control_frame->size());
3319 EXPECT_TRUE(visitor.header_buffer_valid_);
3320 EXPECT_EQ(0, visitor.error_count_);
3321 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3322 EXPECT_EQ(16, visitor.continuation_count_);
3323 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3326 // Check that the framer stops delivering header data chunks once the visitor
3327 // declares it doesn't want any more. This is important to guard against
3328 // "zip bomb" types of attacks.
3329 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3330 const size_t kHeaderBufferChunks = 4;
3331 const size_t kHeaderBufferSize =
3332 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3333 const size_t kBigValueSize = kHeaderBufferSize * 2;
3334 string big_value(kBigValueSize, 'x');
3335 SpdyFramer framer(spdy_version_);
3336 SpdyHeadersIR headers(1);
3337 headers.set_priority(1);
3338 headers.set_fin(true);
3339 headers.SetHeader("aa", big_value);
3340 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3341 EXPECT_TRUE(control_frame.get() != NULL);
3342 TestSpdyVisitor visitor(spdy_version_);
3343 visitor.set_header_buffer_size(kHeaderBufferSize);
3344 visitor.use_compression_ = true;
3345 visitor.SimulateInFramer(
3346 reinterpret_cast<unsigned char*>(control_frame->data()),
3347 control_frame->size());
3348 EXPECT_FALSE(visitor.header_buffer_valid_);
3349 EXPECT_EQ(1, visitor.error_count_);
3350 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3351 visitor.framer_.error_code())
3352 << SpdyFramer::ErrorCodeToString(framer.error_code());
3354 // The framer should have stoped delivering chunks after the visitor
3355 // signaled "stop" by returning false from OnControlFrameHeaderData().
3357 // control_frame_header_data_count_ depends on the random sequence
3358 // produced by rand(), so adding, removing or running single tests
3359 // alters this value. The best we can do is assert that it happens
3360 // at least kHeaderBufferChunks + 1.
3361 EXPECT_LE(kHeaderBufferChunks + 1,
3362 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3363 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3365 // The framer should not have sent half-close to the visitor.
3366 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3369 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3370 if (spdy_version_ > SPDY3) {
3371 // Deflate compression doesn't apply to HPACK.
3372 return;
3374 SpdyFramer framer(spdy_version_);
3375 framer.set_enable_compression(false);
3376 // Construct a SYN_STREAM control frame without compressing the header block,
3377 // and have the framer try to decompress it. This will cause the framer to
3378 // deal with a decompression error.
3379 SpdySynStreamIR syn_stream(1);
3380 syn_stream.set_priority(1);
3381 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3382 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3383 TestSpdyVisitor visitor(spdy_version_);
3384 visitor.use_compression_ = true;
3385 visitor.SimulateInFramer(
3386 reinterpret_cast<unsigned char*>(control_frame->data()),
3387 control_frame->size());
3388 EXPECT_EQ(1, visitor.error_count_);
3389 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3390 << SpdyFramer::ErrorCodeToString(framer.error_code());
3391 EXPECT_EQ(0u, visitor.header_buffer_length_);
3394 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3395 SpdyFramer framer(spdy_version_);
3396 // Create a GoAway frame that has a few extra bytes at the end.
3397 // We create enough overhead to overflow the framer's control frame buffer.
3398 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize);
3399 const unsigned char length = 1 + SpdyFramer::kControlFrameBufferSize;
3400 const unsigned char kV3FrameData[] = { // Also applies for V2.
3401 0x80, spdy_version_ch_, 0x00, 0x07,
3402 0x00, 0x00, 0x00, length,
3403 0x00, 0x00, 0x00, 0x00, // Stream ID
3404 0x00, 0x00, 0x00, 0x00, // Status
3407 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3408 // since it may carry opaque data. Verify that minimal length is tested.
3409 const unsigned char less_than_min_length =
3410 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3411 const unsigned char kV4FrameData[] = {
3412 0x00, 0x00, static_cast<uint8>(less_than_min_length), 0x07,
3413 0x00, 0x00, 0x00, 0x00,
3414 0x00, 0x00, 0x00, 0x00, // Stream Id
3415 0x00, 0x00, 0x00, 0x00, // Status
3416 0x00,
3418 const size_t pad_length =
3419 length + framer.GetControlFrameHeaderSize() -
3420 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3421 string pad('A', pad_length);
3422 TestSpdyVisitor visitor(spdy_version_);
3424 if (IsSpdy4()) {
3425 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3426 } else {
3427 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3429 visitor.SimulateInFramer(
3430 reinterpret_cast<const unsigned char*>(pad.c_str()),
3431 pad.length());
3433 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3434 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3435 visitor.framer_.error_code())
3436 << SpdyFramer::ErrorCodeToString(framer.error_code());
3437 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3440 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3441 SpdyFramer framer(spdy_version_);
3442 SpdySettingsIR settings_ir;
3443 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3444 SetFrameLength(control_frame.get(), 0, spdy_version_);
3445 TestSpdyVisitor visitor(spdy_version_);
3446 visitor.use_compression_ = false;
3447 visitor.SimulateInFramer(
3448 reinterpret_cast<unsigned char*>(control_frame->data()),
3449 framer.GetControlFrameHeaderSize());
3450 if (spdy_version_ <= SPDY3) {
3451 // Should generate an error, since zero-len settings frames are unsupported.
3452 EXPECT_EQ(1, visitor.error_count_);
3453 } else {
3454 // Zero-len settings frames are permitted as of SPDY 4.
3455 EXPECT_EQ(0, visitor.error_count_);
3459 // Tests handling of SETTINGS frames with invalid length.
3460 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3461 SpdyFramer framer(spdy_version_);
3462 SpdySettingsIR settings_ir;
3464 // Add a setting to pad the frame so that we don't get a buffer overflow when
3465 // calling SimulateInFramer() below.
3466 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3467 false,
3468 false,
3469 0x00000002);
3470 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3471 const size_t kNewLength = 14;
3472 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3473 TestSpdyVisitor visitor(spdy_version_);
3474 visitor.use_compression_ = false;
3475 visitor.SimulateInFramer(
3476 reinterpret_cast<unsigned char*>(control_frame->data()),
3477 framer.GetControlFrameHeaderSize() + kNewLength);
3478 // Should generate an error, since its not possible to have a
3479 // settings frame of length kNewLength.
3480 EXPECT_EQ(1, visitor.error_count_);
3483 // Tests handling of SETTINGS frames larger than the frame buffer size.
3484 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3485 SpdyFramer framer(spdy_version_);
3486 SpdySettingsIR settings_ir;
3487 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3488 false, // persist
3489 false, // persisted
3491 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3492 false, // persist
3493 false, // persisted
3495 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3496 false, // persist
3497 false, // persisted
3500 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3501 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3502 control_frame->size());
3503 TestSpdyVisitor visitor(spdy_version_);
3504 visitor.use_compression_ = false;
3506 // Read all at once.
3507 visitor.SimulateInFramer(
3508 reinterpret_cast<unsigned char*>(control_frame->data()),
3509 control_frame->size());
3510 EXPECT_EQ(0, visitor.error_count_);
3511 EXPECT_EQ(3, visitor.setting_count_);
3512 if (spdy_version_ > SPDY3) {
3513 EXPECT_EQ(1, visitor.settings_ack_sent_);
3516 // Read data in small chunks.
3517 size_t framed_data = 0;
3518 size_t unframed_data = control_frame->size();
3519 size_t kReadChunkSize = 5; // Read five bytes at a time.
3520 while (unframed_data > 0) {
3521 size_t to_read = min(kReadChunkSize, unframed_data);
3522 visitor.SimulateInFramer(
3523 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3524 to_read);
3525 unframed_data -= to_read;
3526 framed_data += to_read;
3528 EXPECT_EQ(0, visitor.error_count_);
3529 EXPECT_EQ(3 * 2, visitor.setting_count_);
3530 if (spdy_version_ > SPDY3) {
3531 EXPECT_EQ(2, visitor.settings_ack_sent_);
3535 // Tests handling of SETTINGS frame with duplicate entries.
3536 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3537 SpdyFramer framer(spdy_version_);
3539 const unsigned char kV2FrameData[] = {
3540 0x80, spdy_version_ch_, 0x00, 0x04,
3541 0x00, 0x00, 0x00, 0x1C,
3542 0x00, 0x00, 0x00, 0x03,
3543 0x01, 0x00, 0x00, 0x00, // 1st Setting
3544 0x00, 0x00, 0x00, 0x02,
3545 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3546 0x00, 0x00, 0x00, 0x03,
3547 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3548 0x00, 0x00, 0x00, 0x03,
3550 const unsigned char kV3FrameData[] = {
3551 0x80, spdy_version_ch_, 0x00, 0x04,
3552 0x00, 0x00, 0x00, 0x1C,
3553 0x00, 0x00, 0x00, 0x03,
3554 0x00, 0x00, 0x00, 0x01, // 1st Setting
3555 0x00, 0x00, 0x00, 0x02,
3556 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3557 0x00, 0x00, 0x00, 0x03,
3558 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3559 0x00, 0x00, 0x00, 0x03,
3561 const unsigned char kV4FrameData[] = {
3562 0x00, 0x00, 0x12, 0x04,
3563 0x00, 0x00, 0x00, 0x00,
3564 0x00, 0x00, 0x01, // 1st Setting
3565 0x00, 0x00, 0x00, 0x02,
3566 0x00, 0x01, // 2nd (duplicate) Setting
3567 0x00, 0x00, 0x00, 0x03,
3568 0x00, 0x03, // 3rd (unprocessed) Setting
3569 0x00, 0x00, 0x00, 0x03,
3572 TestSpdyVisitor visitor(spdy_version_);
3573 visitor.use_compression_ = false;
3574 if (IsSpdy2()) {
3575 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3576 } else if (IsSpdy3()) {
3577 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3578 } else {
3579 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3582 if (!IsSpdy4()) {
3583 EXPECT_EQ(1, visitor.setting_count_);
3584 EXPECT_EQ(1, visitor.error_count_);
3585 } else {
3586 // In SPDY 4+, duplicate settings are allowed;
3587 // each setting replaces the previous value for that setting.
3588 EXPECT_EQ(3, visitor.setting_count_);
3589 EXPECT_EQ(0, visitor.error_count_);
3590 EXPECT_EQ(1, visitor.settings_ack_sent_);
3594 // Tests handling of SETTINGS frame with a setting we don't recognize.
3595 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3596 SpdyFramer framer(spdy_version_);
3598 const unsigned char kV2FrameData[] = {
3599 0x80, spdy_version_ch_, 0x00, 0x04,
3600 0x00, 0x00, 0x00, 0x1C,
3601 0x00, 0x00, 0x00, 0x01,
3602 0x10, 0x00, 0x00, 0x00, // 1st Setting
3603 0x00, 0x00, 0x00, 0x02,
3605 const unsigned char kV3FrameData[] = {
3606 0x80, spdy_version_ch_, 0x00, 0x04,
3607 0x00, 0x00, 0x00, 0x1C,
3608 0x00, 0x00, 0x00, 0x01,
3609 0x00, 0x00, 0x00, 0x10, // 1st Setting
3610 0x00, 0x00, 0x00, 0x02,
3612 const unsigned char kV4FrameData[] = {
3613 0x00, 0x00, 0x06, 0x04,
3614 0x00, 0x00, 0x00, 0x00,
3615 0x00, 0x00, 0x10, // 1st Setting
3616 0x00, 0x00, 0x00, 0x02,
3619 TestSpdyVisitor visitor(spdy_version_);
3620 visitor.use_compression_ = false;
3621 if (IsSpdy2()) {
3622 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3623 } else if (IsSpdy3()) {
3624 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3625 } else {
3626 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3629 if (!IsSpdy4()) {
3630 EXPECT_EQ(0, visitor.setting_count_);
3631 EXPECT_EQ(1, visitor.error_count_);
3632 } else {
3633 // In SPDY 4+, we ignore unknown settings because of extensions.
3634 EXPECT_EQ(0, visitor.setting_count_);
3635 EXPECT_EQ(0, visitor.error_count_);
3639 // Tests handling of SETTINGS frame with entries out of order.
3640 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
3641 SpdyFramer framer(spdy_version_);
3643 const unsigned char kV2FrameData[] = {
3644 0x80, spdy_version_ch_, 0x00, 0x04,
3645 0x00, 0x00, 0x00, 0x1C,
3646 0x00, 0x00, 0x00, 0x03,
3647 0x02, 0x00, 0x00, 0x00, // 1st Setting
3648 0x00, 0x00, 0x00, 0x02,
3649 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
3650 0x00, 0x00, 0x00, 0x03,
3651 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3652 0x00, 0x00, 0x00, 0x03,
3654 const unsigned char kV3FrameData[] = {
3655 0x80, spdy_version_ch_, 0x00, 0x04,
3656 0x00, 0x00, 0x00, 0x1C,
3657 0x00, 0x00, 0x00, 0x03,
3658 0x00, 0x00, 0x00, 0x02, // 1st Setting
3659 0x00, 0x00, 0x00, 0x02,
3660 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
3661 0x00, 0x00, 0x00, 0x03,
3662 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
3663 0x00, 0x00, 0x00, 0x03,
3665 const unsigned char kV4FrameData[] = {
3666 0x00, 0x00, 0x12, 0x04,
3667 0x00, 0x00, 0x00, 0x00,
3668 0x00, 0x00, 0x02, // 1st Setting
3669 0x00, 0x00, 0x00, 0x02,
3670 0x00, 0x01, // 2nd (out of order) Setting
3671 0x00, 0x00, 0x00, 0x03,
3672 0x00, 0x03, // 3rd (unprocessed) Setting
3673 0x00, 0x00, 0x00, 0x03,
3676 TestSpdyVisitor visitor(spdy_version_);
3677 visitor.use_compression_ = false;
3678 if (IsSpdy2()) {
3679 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3680 } else if (IsSpdy3()) {
3681 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3682 } else {
3683 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3686 if (!IsSpdy4()) {
3687 EXPECT_EQ(1, visitor.setting_count_);
3688 EXPECT_EQ(1, visitor.error_count_);
3689 } else {
3690 // In SPDY 4+, settings are allowed in any order.
3691 EXPECT_EQ(3, visitor.setting_count_);
3692 EXPECT_EQ(0, visitor.error_count_);
3696 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
3697 if (spdy_version_ <= SPDY3) {
3698 return;
3700 SpdyFramer framer(spdy_version_);
3702 const unsigned char kFrameData[] = {
3703 0x00, 0x00, 0x00, 0x04, 0x01,
3704 0x00, 0x00, 0x00, 0x00,
3707 TestSpdyVisitor visitor(spdy_version_);
3708 visitor.use_compression_ = false;
3709 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
3711 EXPECT_EQ(0, visitor.error_count_);
3712 EXPECT_EQ(0, visitor.setting_count_);
3713 EXPECT_EQ(1, visitor.settings_ack_received_);
3716 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
3717 if (spdy_version_ <= SPDY3) {
3718 return;
3721 const int kPaddingLen = 119;
3722 const char data_payload[] = "hello";
3724 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3725 SpdyFramer framer(spdy_version_);
3726 framer.set_visitor(&visitor);
3728 SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
3729 data_ir.set_padding_len(kPaddingLen);
3730 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
3731 ASSERT_TRUE(frame.get() != NULL);
3733 int bytes_consumed = 0;
3735 // Send the frame header.
3736 EXPECT_CALL(visitor, OnDataFrameHeader(1,
3737 kPaddingLen + strlen(data_payload),
3738 false));
3739 CHECK_EQ(framer.GetDataFrameMinimumSize(),
3740 framer.ProcessInput(frame->data(),
3741 framer.GetDataFrameMinimumSize()));
3742 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH);
3743 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3744 bytes_consumed += framer.GetDataFrameMinimumSize();
3746 // Send the padding length field.
3747 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
3748 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3749 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3750 bytes_consumed += 1;
3752 // Send the first two bytes of the data payload, i.e., "he".
3753 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
3754 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
3755 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3756 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3757 bytes_consumed += 2;
3759 // Send the rest three bytes of the data payload, i.e., "llo".
3760 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
3761 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
3762 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3763 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3764 bytes_consumed += 3;
3766 // Send the first 100 bytes of the padding payload.
3767 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false));
3768 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
3769 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3770 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3771 bytes_consumed += 100;
3773 // Send rest of the padding payload.
3774 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 18, false));
3775 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
3776 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
3777 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
3780 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
3781 SpdyFramer framer(spdy_version_);
3782 scoped_ptr<SpdyFrame> control_frame(
3783 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3784 TestSpdyVisitor visitor(spdy_version_);
3785 visitor.SimulateInFramer(
3786 reinterpret_cast<unsigned char*>(control_frame->data()),
3787 control_frame->size());
3788 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3789 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3792 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
3793 if (!IsSpdy3()) {
3794 return;
3796 SpdyFramer framer(spdy_version_);
3797 const unsigned char kV3FrameData[] = { // Also applies for V2.
3798 0x80, spdy_version_ch_, 0x00, 0x0A,
3799 0x00, 0x00, 0x00, 0x33,
3800 0x00, 0x03, 0x00, 0x00,
3801 0x00, 0x05, 'p', 'r',
3802 'o', 'o', 'f', 0x00,
3803 0x00, 0x00, 0x06, 'a',
3804 ' ', 'c', 'e', 'r',
3805 't', 0x00, 0x00, 0x00,
3806 0x0C, 'a', 'n', 'o',
3807 't', 'h', 'e', 'r',
3808 ' ', 'c', 'e', 'r',
3809 't', 0x00, 0x00, 0x00,
3810 0x0A, 'f', 'i', 'n',
3811 'a', 'l', ' ', 'c',
3812 'e', 'r', 't',
3814 TestSpdyVisitor visitor(spdy_version_);
3815 visitor.use_compression_ = false;
3816 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
3817 EXPECT_EQ(0, visitor.error_count_);
3820 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
3821 if (!IsSpdy3()) {
3822 return;
3824 SpdyFramer framer(spdy_version_);
3825 const unsigned char kV3FrameData[] = { // Also applies for V2.
3826 0x80, spdy_version_ch_, 0x00, 0x0A,
3827 0x00, 0x00, 0x00, 0x33,
3828 0x00, 0x03, 0x00, 0x00,
3829 0x00, 0x05, 'p', 'r',
3830 'o', 'o', 'f', 0x00,
3831 0x00, 0x00, 0x06, 'a',
3832 ' ', 'c', 'e', 'r',
3833 't', 0x00, 0x00, 0x00,
3834 0x0C, 'a', 'n', 'o',
3835 't', 'h', 'e', 'r',
3836 ' ', 'c', 'e', 'r',
3837 't', 0x00, 0x00, 0x00,
3838 0x0A, 'f', 'i', 'n',
3839 'a', 'l', ' ', 'c',
3840 'e', 'r', 't',
3842 TestSpdyVisitor visitor(spdy_version_);
3843 visitor.use_compression_ = false;
3844 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
3845 arraysize(kV3FrameData));
3846 scoped_ptr<SpdyFrame> control_frame(
3847 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3848 multiple_frame_data.append(string(control_frame->data(),
3849 control_frame->size()));
3850 visitor.SimulateInFramer(
3851 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
3852 multiple_frame_data.length());
3853 EXPECT_EQ(0, visitor.error_count_);
3854 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3855 EXPECT_EQ(2u, visitor.last_window_update_delta_);
3858 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
3859 if (spdy_version_ <= SPDY3) {
3860 return;
3863 SpdyFramer framer(spdy_version_);
3864 SpdyPushPromiseIR push_promise(42, 57);
3865 push_promise.SetHeader("foo", "bar");
3866 push_promise.SetHeader("bar", "foofoo");
3867 SpdyHeaderBlock headers = push_promise.name_value_block();
3868 scoped_ptr<SpdySerializedFrame> frame(
3869 framer.SerializePushPromise(push_promise));
3870 EXPECT_TRUE(frame.get() != NULL);
3871 TestSpdyVisitor visitor(spdy_version_);
3872 visitor.use_compression_ = true;
3873 visitor.SimulateInFramer(
3874 reinterpret_cast<unsigned char*>(frame->data()),
3875 frame->size());
3876 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
3877 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
3878 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3881 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
3882 if (spdy_version_ <= SPDY3) {
3883 return;
3886 const unsigned char kInput[] = {
3887 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
3888 0x00, 0x00, 0x00, 0x01, // Stream 1
3889 0x03, // Padding of 3.
3890 0x00, 0x06, 0x63, 0x6f,
3891 0x6f, 0x6b, 0x69, 0x65,
3892 0x07, 0x66, 0x6f, 0x6f,
3893 0x3d, 0x62, 0x61, 0x72,
3894 0x00, 0x00, 0x00,
3896 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3897 0x00, 0x00, 0x00, 0x01, // Stream 1
3898 0x00, 0x06, 0x63, 0x6f,
3899 0x6f, 0x6b, 0x69, 0x65,
3900 0x08, 0x62, 0x61, 0x7a,
3901 0x3d, 0x62, 0x69, 0x6e,
3902 0x67, 0x00, 0x06, 0x63,
3904 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3905 0x00, 0x00, 0x00, 0x01, // Stream 1
3906 0x6f, 0x6f, 0x6b, 0x69,
3907 0x65, 0x00, 0x00, 0x04,
3908 0x6e, 0x61, 0x6d, 0x65,
3909 0x05, 0x76, 0x61, 0x6c,
3910 0x75, 0x65,
3913 TestSpdyVisitor visitor(spdy_version_);
3914 visitor.SimulateInFramer(kInput, sizeof(kInput));
3916 EXPECT_EQ(0, visitor.error_count_);
3917 EXPECT_EQ(1, visitor.headers_frame_count_);
3918 EXPECT_EQ(2, visitor.continuation_count_);
3919 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3920 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3922 EXPECT_THAT(visitor.headers_, ElementsAre(
3923 Pair("cookie", "foo=bar; baz=bing; "),
3924 Pair("name", "value")));
3927 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
3928 if (spdy_version_ <= SPDY3) {
3929 return;
3932 const unsigned char kInput[] = {
3933 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
3934 0x00, 0x00, 0x00, 0x01, // Stream 1
3935 0x00, 0x06, 0x63, 0x6f,
3936 0x6f, 0x6b, 0x69, 0x65,
3937 0x07, 0x66, 0x6f, 0x6f,
3938 0x3d, 0x62, 0x61, 0x72,
3940 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3941 0x00, 0x00, 0x00, 0x01, // Stream 1
3942 0x00, 0x06, 0x63, 0x6f,
3943 0x6f, 0x6b, 0x69, 0x65,
3944 0x08, 0x62, 0x61, 0x7a,
3945 0x3d, 0x62, 0x69, 0x6e,
3946 0x67, 0x00, 0x06, 0x63,
3948 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3949 0x00, 0x00, 0x00, 0x01, // Stream 1
3950 0x6f, 0x6f, 0x6b, 0x69,
3951 0x65, 0x00, 0x00, 0x04,
3952 0x6e, 0x61, 0x6d, 0x65,
3953 0x05, 0x76, 0x61, 0x6c,
3954 0x75, 0x65,
3957 SpdyFramer framer(spdy_version_);
3958 TestSpdyVisitor visitor(spdy_version_);
3959 visitor.SimulateInFramer(kInput, sizeof(kInput));
3961 EXPECT_EQ(0, visitor.error_count_);
3962 EXPECT_EQ(1, visitor.headers_frame_count_);
3963 EXPECT_EQ(2, visitor.continuation_count_);
3964 EXPECT_EQ(1, visitor.fin_flag_count_);
3965 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3966 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3968 EXPECT_THAT(visitor.headers_, ElementsAre(
3969 Pair("cookie", "foo=bar; baz=bing; "),
3970 Pair("name", "value")));
3973 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
3974 if (spdy_version_ <= SPDY3) {
3975 return;
3978 const unsigned char kInput[] = {
3979 0x00, 0x00, 0x17, 0x05, 0x08, // PUSH_PROMISE: PADDED
3980 0x00, 0x00, 0x00, 0x01, // Stream 1
3981 0x00, 0x00, 0x00, 0x2A, // Promised stream 42
3982 0x02, // Padding of 2.
3983 0x00, 0x06, 0x63, 0x6f,
3984 0x6f, 0x6b, 0x69, 0x65,
3985 0x07, 0x66, 0x6f, 0x6f,
3986 0x3d, 0x62, 0x61, 0x72,
3987 0x00, 0x00,
3989 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
3990 0x00, 0x00, 0x00, 0x01, // Stream 1
3991 0x00, 0x06, 0x63, 0x6f,
3992 0x6f, 0x6b, 0x69, 0x65,
3993 0x08, 0x62, 0x61, 0x7a,
3994 0x3d, 0x62, 0x69, 0x6e,
3995 0x67, 0x00, 0x06, 0x63,
3997 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
3998 0x00, 0x00, 0x00, 0x01, // Stream 1
3999 0x6f, 0x6f, 0x6b, 0x69,
4000 0x65, 0x00, 0x00, 0x04,
4001 0x6e, 0x61, 0x6d, 0x65,
4002 0x05, 0x76, 0x61, 0x6c,
4003 0x75, 0x65,
4006 SpdyFramer framer(spdy_version_);
4007 TestSpdyVisitor visitor(spdy_version_);
4008 visitor.SimulateInFramer(kInput, sizeof(kInput));
4010 EXPECT_EQ(0, visitor.error_count_);
4011 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4012 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4013 EXPECT_EQ(2, visitor.continuation_count_);
4014 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4015 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4017 EXPECT_THAT(visitor.headers_, ElementsAre(
4018 Pair("cookie", "foo=bar; baz=bing; "),
4019 Pair("name", "value")));
4022 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4023 if (spdy_version_ <= SPDY3) {
4024 return;
4027 const unsigned char kInput[] = {
4028 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4029 0x00, 0x00, 0x00, 0x01, // Stream 1
4030 0x00, 0x06, 0x63, 0x6f,
4031 0x6f, 0x6b, 0x69, 0x65,
4032 0x07, 0x66, 0x6f, 0x6f,
4033 0x3d, 0x62, 0x61, 0x72,
4035 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4036 0x00, 0x00, 0x00, 0x02, // Stream 2
4037 0x00, 0x06, 0x63, 0x6f,
4038 0x6f, 0x6b, 0x69, 0x65,
4039 0x08, 0x62, 0x61, 0x7a,
4040 0x3d, 0x62, 0x69, 0x6e,
4041 0x67, 0x00, 0x06, 0x63,
4044 SpdyFramer framer(spdy_version_);
4045 TestSpdyVisitor visitor(spdy_version_);
4046 framer.set_visitor(&visitor);
4047 visitor.SimulateInFramer(kInput, sizeof(kInput));
4049 EXPECT_EQ(1, visitor.error_count_);
4050 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4051 visitor.framer_.error_code())
4052 << SpdyFramer::ErrorCodeToString(framer.error_code());
4053 EXPECT_EQ(1, visitor.headers_frame_count_);
4054 EXPECT_EQ(0, visitor.continuation_count_);
4055 EXPECT_EQ(0u, visitor.header_buffer_length_);
4058 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4059 if (spdy_version_ <= SPDY3) {
4060 return;
4063 const unsigned char kInput[] = {
4064 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4065 0x00, 0x00, 0x00, 0x01, // Stream 1
4066 0x00, 0x06, 0x63, 0x6f,
4067 0x6f, 0x6b, 0x69, 0x65,
4068 0x07, 0x66, 0x6f, 0x6f,
4069 0x3d, 0x62, 0x61, 0x72,
4072 SpdyFramer framer(spdy_version_);
4073 TestSpdyVisitor visitor(spdy_version_);
4074 framer.set_visitor(&visitor);
4075 visitor.SimulateInFramer(kInput, sizeof(kInput));
4077 EXPECT_EQ(1, visitor.error_count_);
4078 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4079 visitor.framer_.error_code())
4080 << SpdyFramer::ErrorCodeToString(framer.error_code());
4081 EXPECT_EQ(0, visitor.continuation_count_);
4082 EXPECT_EQ(0u, visitor.header_buffer_length_);
4085 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4086 if (spdy_version_ <= SPDY3) {
4087 return;
4090 const unsigned char kInput[] = {
4091 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4092 0x00, 0x00, 0x00, 0x01, // Stream 1
4093 0x00, 0x06, 0x63, 0x6f,
4094 0x6f, 0x6b, 0x69, 0x65,
4095 0x07, 0x66, 0x6f, 0x6f,
4096 0x3d, 0x62, 0x61, 0x72,
4098 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4099 0x00, 0x00, 0x00, 0x04,
4100 0xde, 0xad, 0xbe, 0xef,
4103 SpdyFramer framer(spdy_version_);
4104 TestSpdyVisitor visitor(spdy_version_);
4105 framer.set_visitor(&visitor);
4106 visitor.SimulateInFramer(kInput, sizeof(kInput));
4108 EXPECT_EQ(1, visitor.error_count_);
4109 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4110 visitor.framer_.error_code())
4111 << SpdyFramer::ErrorCodeToString(framer.error_code());
4112 EXPECT_EQ(1, visitor.headers_frame_count_);
4113 EXPECT_EQ(0, visitor.continuation_count_);
4114 EXPECT_EQ(0u, visitor.header_buffer_length_);
4115 EXPECT_EQ(0, visitor.data_frame_count_);
4118 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4119 if (spdy_version_ <= SPDY3) {
4120 return;
4123 const unsigned char kInput[] = {
4124 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4125 0x00, 0x00, 0x00, 0x01, // Stream 1
4126 0x00, 0x06, 0x63, 0x6f,
4127 0x6f, 0x6b, 0x69, 0x65,
4128 0x07, 0x66, 0x6f, 0x6f,
4129 0x3d, 0x62, 0x61, 0x72,
4131 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4132 0x00, 0x00, 0x00, 0x01, // Stream 1
4133 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4134 0x6f, 0x6b, 0x69, 0x65,
4135 0x08, 0x62, 0x61, 0x7a,
4136 0x3d, 0x62, 0x69, 0x6e,
4137 0x67, 0x00, 0x06, 0x63,
4140 SpdyFramer framer(spdy_version_);
4141 TestSpdyVisitor visitor(spdy_version_);
4142 framer.set_visitor(&visitor);
4143 visitor.SimulateInFramer(kInput, sizeof(kInput));
4145 EXPECT_EQ(1, visitor.error_count_);
4146 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4147 visitor.framer_.error_code())
4148 << SpdyFramer::ErrorCodeToString(framer.error_code());
4149 EXPECT_EQ(1, visitor.headers_frame_count_);
4150 EXPECT_EQ(0, visitor.continuation_count_);
4151 EXPECT_EQ(0u, visitor.header_buffer_length_);
4152 EXPECT_EQ(0, visitor.data_frame_count_);
4155 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4156 if (spdy_version_ <= SPDY3) {
4157 return;
4159 const unsigned char kInput[] = {
4160 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4161 0x00, 0x00, 0x00, 0x01, // Stream 1
4162 0xde, 0xad, 0xbe, 0xef,
4163 0xde, 0xad, 0xbe, 0xef,
4164 0xde, 0xad, 0xbe, 0xef,
4167 TestSpdyVisitor visitor(spdy_version_);
4168 visitor.SimulateInFramer(kInput, sizeof(kInput));
4170 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4171 EXPECT_EQ(0, visitor.error_count_);
4172 EXPECT_EQ(12, visitor.data_bytes_);
4173 EXPECT_EQ(0, visitor.fin_frame_count_);
4174 EXPECT_EQ(0, visitor.fin_flag_count_);
4177 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4178 if (spdy_version_ <= SPDY3) {
4179 return;
4181 const unsigned char kInput[] = {
4182 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4183 0x00, 0x00, 0x00, 0x01, // Stream 1
4184 0x00, 0x06, 0x63, 0x6f,
4185 0x6f, 0x6b, 0x69, 0x65,
4186 0x07, 0x66, 0x6f, 0x6f,
4187 0x3d, 0x62, 0x61, 0x72,
4190 TestSpdyVisitor visitor(spdy_version_);
4191 visitor.SimulateInFramer(kInput, sizeof(kInput));
4193 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4194 EXPECT_EQ(0, visitor.error_count_);
4195 EXPECT_EQ(1, visitor.headers_frame_count_);
4196 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4198 EXPECT_THAT(visitor.headers_, ElementsAre(
4199 Pair("cookie", "foo=bar")));
4202 TEST_P(SpdyFramerTest, ReadGarbage) {
4203 SpdyFramer framer(spdy_version_);
4204 unsigned char garbage_frame[256];
4205 memset(garbage_frame, ~0, sizeof(garbage_frame));
4206 TestSpdyVisitor visitor(spdy_version_);
4207 visitor.use_compression_ = false;
4208 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4209 EXPECT_EQ(1, visitor.error_count_);
4212 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4213 if (spdy_version_ <= SPDY3) {
4214 return;
4216 SpdyFramer framer(spdy_version_);
4218 // The unrecognized frame type should still have a valid length.
4219 const unsigned char unknown_frame[] = {
4220 0x00, 0x00, 0x08, 0xff, 0xff,
4221 0xff, 0xff, 0xff, 0xff,
4222 0xff, 0xff, 0xff, 0xff,
4223 0xff, 0xff, 0xff, 0xff,
4225 TestSpdyVisitor visitor(spdy_version_);
4227 // Simulate the case where the stream id validation checks out.
4228 visitor.on_unknown_frame_result_ = true;
4229 visitor.use_compression_ = false;
4230 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4231 EXPECT_EQ(0, visitor.error_count_);
4233 // Follow it up with a valid control frame to make sure we handle
4234 // subsequent frames correctly.
4235 SpdySettingsIR settings_ir;
4236 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4237 false, // persist
4238 false, // persisted
4239 10);
4240 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4241 visitor.SimulateInFramer(
4242 reinterpret_cast<unsigned char*>(control_frame->data()),
4243 control_frame->size());
4244 EXPECT_EQ(0, visitor.error_count_);
4245 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4246 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4249 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4250 if (!IsSpdy4()) {
4251 return;
4253 SpdyFramer framer(spdy_version_);
4254 const unsigned char kFrameData[] = {
4255 0x00, 0x00, 0x08, 0xff, 0xff,
4256 0xff, 0xff, 0xff, 0xff,
4257 0xff, 0xff, 0xff, 0xff,
4258 0xff, 0xff, 0xff, 0xff,
4260 TestSpdyVisitor visitor(spdy_version_);
4261 visitor.use_compression_ = false;
4262 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4263 EXPECT_EQ(1, visitor.error_count_);
4266 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4267 if (IsSpdy4()) {
4268 // Not valid for SPDY 4 since there is no version field.
4269 return;
4271 SpdyFramer framer(spdy_version_);
4272 const unsigned char kFrameData[] = {
4273 0x80, spdy_version_ch_, 0xff, 0xff,
4274 0xff, 0xff, 0xff, 0xff,
4276 TestSpdyVisitor visitor(spdy_version_);
4277 visitor.use_compression_ = false;
4278 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4279 EXPECT_EQ(1, visitor.error_count_);
4282 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4283 if (spdy_version_ <= SPDY3) {
4284 return;
4286 const unsigned char kInput[] = {
4287 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4288 0x00, 0x00, 0x00, 0x01, // Stream 1
4289 0xef, 0xef, 0xff, 0xff,
4290 0xff, 0xff, 0xff, 0xff,
4291 0xff, 0xff, 0xff, 0xff,
4292 0xff, 0xff, 0xff, 0xff,
4293 0xff, 0xff,
4296 TestSpdyVisitor visitor(spdy_version_);
4297 visitor.SimulateInFramer(kInput, arraysize(kInput));
4298 EXPECT_EQ(1, visitor.error_count_);
4301 TEST_P(SpdyFramerTest, SizesTest) {
4302 SpdyFramer framer(spdy_version_);
4303 if (IsSpdy4() || IsSpdy5()) {
4304 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4305 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4306 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4307 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4308 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4309 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4310 EXPECT_EQ(17u, framer.GetPingSize());
4311 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4312 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4313 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4314 EXPECT_EQ(9u, framer.GetBlockedSize());
4315 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4316 EXPECT_EQ(18u, framer.GetAltSvcMinimumSize());
4317 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4318 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4319 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4320 } else {
4321 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4322 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4323 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4324 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4325 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4326 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4327 EXPECT_EQ(12u, framer.GetPingSize());
4328 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4329 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4330 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4331 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4332 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4333 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4337 TEST_P(SpdyFramerTest, StateToStringTest) {
4338 EXPECT_STREQ("ERROR",
4339 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4340 EXPECT_STREQ("AUTO_RESET",
4341 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4342 EXPECT_STREQ("RESET",
4343 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4344 EXPECT_STREQ("READING_COMMON_HEADER",
4345 SpdyFramer::StateToString(
4346 SpdyFramer::SPDY_READING_COMMON_HEADER));
4347 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4348 SpdyFramer::StateToString(
4349 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4350 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4351 SpdyFramer::StateToString(
4352 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4353 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4354 SpdyFramer::StateToString(
4355 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4356 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4357 SpdyFramer::StateToString(
4358 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4359 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4360 SpdyFramer::StateToString(
4361 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4362 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4363 SpdyFramer::StateToString(
4364 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4365 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4366 SpdyFramer::StateToString(
4367 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4368 EXPECT_STREQ("UNKNOWN_STATE",
4369 SpdyFramer::StateToString(
4370 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4373 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4374 EXPECT_STREQ("NO_ERROR",
4375 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4376 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4377 SpdyFramer::ErrorCodeToString(
4378 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4379 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4380 SpdyFramer::ErrorCodeToString(
4381 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4382 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4383 SpdyFramer::ErrorCodeToString(
4384 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4385 EXPECT_STREQ("UNSUPPORTED_VERSION",
4386 SpdyFramer::ErrorCodeToString(
4387 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4388 EXPECT_STREQ("DECOMPRESS_FAILURE",
4389 SpdyFramer::ErrorCodeToString(
4390 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4391 EXPECT_STREQ("COMPRESS_FAILURE",
4392 SpdyFramer::ErrorCodeToString(
4393 SpdyFramer::SPDY_COMPRESS_FAILURE));
4394 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4395 SpdyFramer::ErrorCodeToString(
4396 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4397 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4398 SpdyFramer::ErrorCodeToString(
4399 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4400 EXPECT_STREQ("UNKNOWN_ERROR",
4401 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4404 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4405 EXPECT_STREQ("INVALID",
4406 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4407 EXPECT_STREQ("PROTOCOL_ERROR",
4408 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4409 EXPECT_STREQ("INVALID_STREAM",
4410 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4411 EXPECT_STREQ("REFUSED_STREAM",
4412 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4413 EXPECT_STREQ("UNSUPPORTED_VERSION",
4414 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4415 EXPECT_STREQ("CANCEL",
4416 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4417 EXPECT_STREQ("INTERNAL_ERROR",
4418 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4419 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4420 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4421 EXPECT_STREQ("UNKNOWN_STATUS",
4422 SpdyFramer::StatusCodeToString(-1));
4425 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4426 EXPECT_STREQ("DATA",
4427 SpdyFramer::FrameTypeToString(DATA));
4428 EXPECT_STREQ("SYN_STREAM",
4429 SpdyFramer::FrameTypeToString(SYN_STREAM));
4430 EXPECT_STREQ("SYN_REPLY",
4431 SpdyFramer::FrameTypeToString(SYN_REPLY));
4432 EXPECT_STREQ("RST_STREAM",
4433 SpdyFramer::FrameTypeToString(RST_STREAM));
4434 EXPECT_STREQ("SETTINGS",
4435 SpdyFramer::FrameTypeToString(SETTINGS));
4436 EXPECT_STREQ("PING",
4437 SpdyFramer::FrameTypeToString(PING));
4438 EXPECT_STREQ("GOAWAY",
4439 SpdyFramer::FrameTypeToString(GOAWAY));
4440 EXPECT_STREQ("HEADERS",
4441 SpdyFramer::FrameTypeToString(HEADERS));
4442 EXPECT_STREQ("WINDOW_UPDATE",
4443 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4444 EXPECT_STREQ("PUSH_PROMISE",
4445 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4446 EXPECT_STREQ("CREDENTIAL",
4447 SpdyFramer::FrameTypeToString(CREDENTIAL));
4448 EXPECT_STREQ("CONTINUATION",
4449 SpdyFramer::FrameTypeToString(CONTINUATION));
4452 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4453 if (IsSpdy4()) {
4454 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4455 return;
4458 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4459 SpdyFramer framer(spdy_version_);
4460 framer.set_visitor(&visitor);
4462 EXPECT_CALL(visitor, OnError(_));
4463 framer.ProcessInput("HTTP/1.1", 8);
4464 EXPECT_TRUE(framer.probable_http_response());
4465 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4466 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4467 << SpdyFramer::ErrorCodeToString(framer.error_code());
4470 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4471 SpdyFramer framer(spdy_version_);
4472 framer.set_visitor(&visitor);
4474 EXPECT_CALL(visitor, OnError(_));
4475 framer.ProcessInput("HTTP/1.0", 8);
4476 EXPECT_TRUE(framer.probable_http_response());
4477 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4478 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4479 << SpdyFramer::ErrorCodeToString(framer.error_code());
4483 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4484 if (spdy_version_ > SPDY3) {
4485 return;
4488 for (int flags = 0; flags < 256; ++flags) {
4489 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4491 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4492 SpdyFramer framer(spdy_version_);
4493 framer.set_visitor(&visitor);
4495 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4496 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4497 SetFrameFlags(frame.get(), flags, spdy_version_);
4499 if (flags & ~DATA_FLAG_FIN) {
4500 EXPECT_CALL(visitor, OnError(_));
4501 } else {
4502 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4503 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4504 if (flags & DATA_FLAG_FIN) {
4505 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4509 framer.ProcessInput(frame->data(), frame->size());
4510 if (flags & ~DATA_FLAG_FIN) {
4511 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4512 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4513 framer.error_code())
4514 << SpdyFramer::ErrorCodeToString(framer.error_code());
4515 } else {
4516 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4517 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4518 << SpdyFramer::ErrorCodeToString(framer.error_code());
4523 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4524 if (spdy_version_ <= SPDY3) {
4525 return;
4528 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4529 DATA_FLAG_PADDED;
4531 for (int flags = 0; flags < 256; ++flags) {
4532 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4534 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4535 SpdyFramer framer(spdy_version_);
4536 framer.set_visitor(&visitor);
4538 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4539 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4540 SetFrameFlags(frame.get(), flags, spdy_version_);
4542 if (flags & ~valid_data_flags) {
4543 EXPECT_CALL(visitor, OnError(_));
4544 } else {
4545 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4546 if (flags & DATA_FLAG_PADDED) {
4547 // Expect Error since we don't set padded in payload.
4548 EXPECT_CALL(visitor, OnError(_));
4549 } else {
4550 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4551 if (flags & DATA_FLAG_FIN) {
4552 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4557 framer.ProcessInput(frame->data(), frame->size());
4558 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
4559 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4560 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4561 framer.error_code())
4562 << SpdyFramer::ErrorCodeToString(framer.error_code());
4563 } else {
4564 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4565 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4566 << SpdyFramer::ErrorCodeToString(framer.error_code());
4571 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4572 if (!IsSpdy2() && !IsSpdy3()) {
4573 // SYN_STREAM not supported in SPDY>3
4574 return;
4576 for (int flags = 0; flags < 256; ++flags) {
4577 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4579 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4580 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4581 SpdyFramer framer(spdy_version_);
4582 framer.set_visitor(&visitor);
4583 framer.set_debug_visitor(&debug_visitor);
4585 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4587 SpdySynStreamIR syn_stream(8);
4588 syn_stream.set_associated_to_stream_id(3);
4589 syn_stream.set_priority(1);
4590 syn_stream.SetHeader("foo", "bar");
4591 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4592 int set_flags = flags;
4593 SetFrameFlags(frame.get(), set_flags, spdy_version_);
4595 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4596 EXPECT_CALL(visitor, OnError(_));
4597 } else {
4598 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
4599 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
4600 flags & CONTROL_FLAG_UNIDIRECTIONAL));
4601 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
4602 .WillRepeatedly(testing::Return(true));
4603 if (flags & DATA_FLAG_FIN) {
4604 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4605 } else {
4606 // Do not close the stream if we are expecting a CONTINUATION frame.
4607 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4611 framer.ProcessInput(frame->data(), frame->size());
4612 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4613 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4614 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4615 framer.error_code())
4616 << SpdyFramer::ErrorCodeToString(framer.error_code());
4617 } else {
4618 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4619 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4620 << SpdyFramer::ErrorCodeToString(framer.error_code());
4625 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
4626 if (!IsSpdy2() && !IsSpdy3()) {
4627 // SYN_REPLY not supported in SPDY>3
4628 return;
4630 for (int flags = 0; flags < 256; ++flags) {
4631 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4633 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4634 SpdyFramer framer(spdy_version_);
4635 framer.set_visitor(&visitor);
4637 SpdySynReplyIR syn_reply(37);
4638 syn_reply.SetHeader("foo", "bar");
4639 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
4640 SetFrameFlags(frame.get(), flags, spdy_version_);
4642 if (flags & ~CONTROL_FLAG_FIN) {
4643 EXPECT_CALL(visitor, OnError(_));
4644 } else {
4645 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
4646 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
4647 .WillRepeatedly(testing::Return(true));
4648 if (flags & DATA_FLAG_FIN) {
4649 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4653 framer.ProcessInput(frame->data(), frame->size());
4654 if (flags & ~CONTROL_FLAG_FIN) {
4655 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4656 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4657 framer.error_code())
4658 << SpdyFramer::ErrorCodeToString(framer.error_code());
4659 } else {
4660 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4661 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4662 << SpdyFramer::ErrorCodeToString(framer.error_code());
4667 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
4668 for (int flags = 0; flags < 256; ++flags) {
4669 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4671 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4672 SpdyFramer framer(spdy_version_);
4673 framer.set_visitor(&visitor);
4675 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
4676 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
4677 SetFrameFlags(frame.get(), flags, spdy_version_);
4679 if (flags != 0) {
4680 EXPECT_CALL(visitor, OnError(_));
4681 } else {
4682 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
4685 framer.ProcessInput(frame->data(), frame->size());
4686 if (flags != 0) {
4687 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4688 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4689 framer.error_code())
4690 << SpdyFramer::ErrorCodeToString(framer.error_code());
4691 } else {
4692 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4693 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4694 << SpdyFramer::ErrorCodeToString(framer.error_code());
4699 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
4700 if (spdy_version_ > SPDY3) { return; }
4701 for (int flags = 0; flags < 256; ++flags) {
4702 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4704 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4705 SpdyFramer framer(spdy_version_);
4706 framer.set_visitor(&visitor);
4708 SpdySettingsIR settings_ir;
4709 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
4710 false,
4711 false,
4712 54321);
4713 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
4714 SetFrameFlags(frame.get(), flags, spdy_version_);
4716 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
4717 EXPECT_CALL(visitor, OnError(_));
4718 } else {
4719 EXPECT_CALL(visitor, OnSettings(
4720 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
4721 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
4722 SETTINGS_FLAG_NONE, 54321));
4723 EXPECT_CALL(visitor, OnSettingsEnd());
4726 framer.ProcessInput(frame->data(), frame->size());
4727 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
4728 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4729 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4730 framer.error_code())
4731 << SpdyFramer::ErrorCodeToString(framer.error_code());
4732 } else {
4733 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4734 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4735 << SpdyFramer::ErrorCodeToString(framer.error_code());
4740 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
4741 if (spdy_version_ <= SPDY3) { return; }
4742 for (int flags = 0; flags < 256; ++flags) {
4743 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4745 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4746 SpdyFramer framer(spdy_version_);
4747 framer.set_visitor(&visitor);
4749 SpdySettingsIR settings_ir;
4750 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
4751 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
4752 SetFrameFlags(frame.get(), flags, spdy_version_);
4754 if (flags != 0) {
4755 EXPECT_CALL(visitor, OnError(_));
4756 } else {
4757 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
4758 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
4759 EXPECT_CALL(visitor, OnSettingsEnd());
4762 framer.ProcessInput(frame->data(), frame->size());
4763 if (flags & ~SETTINGS_FLAG_ACK) {
4764 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4765 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4766 framer.error_code())
4767 << SpdyFramer::ErrorCodeToString(framer.error_code());
4768 } else if (flags & SETTINGS_FLAG_ACK) {
4769 // The frame is invalid because ACK frames should have no payload.
4770 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4771 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4772 framer.error_code())
4773 << SpdyFramer::ErrorCodeToString(framer.error_code());
4774 } else {
4775 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4776 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4777 << SpdyFramer::ErrorCodeToString(framer.error_code());
4782 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
4783 for (int flags = 0; flags < 256; ++flags) {
4784 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4786 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4787 SpdyFramer framer(spdy_version_);
4788 framer.set_visitor(&visitor);
4790 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
4791 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
4792 SetFrameFlags(frame.get(), flags, spdy_version_);
4794 if (flags != 0) {
4795 EXPECT_CALL(visitor, OnError(_));
4796 } else {
4797 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
4800 framer.ProcessInput(frame->data(), frame->size());
4801 if (flags != 0) {
4802 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4803 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4804 framer.error_code())
4805 << SpdyFramer::ErrorCodeToString(framer.error_code());
4806 } else {
4807 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4808 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4809 << SpdyFramer::ErrorCodeToString(framer.error_code());
4814 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
4815 for (int flags = 0; flags < 256; ++flags) {
4816 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4818 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4819 SpdyFramer framer(spdy_version_);
4820 framer.set_visitor(&visitor);
4822 SpdyHeadersIR headers_ir(57);
4823 if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
4824 headers_ir.set_priority(3);
4825 headers_ir.set_has_priority(true);
4827 headers_ir.SetHeader("foo", "bar");
4828 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
4829 int set_flags = flags;
4830 if (IsSpdy4()) {
4831 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
4832 // and implement framing.
4833 set_flags &= ~HEADERS_FLAG_PADDED;
4835 SetFrameFlags(frame.get(), set_flags, spdy_version_);
4837 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
4838 EXPECT_CALL(visitor, OnError(_));
4839 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
4840 HEADERS_FLAG_END_HEADERS |
4841 HEADERS_FLAG_END_SEGMENT |
4842 HEADERS_FLAG_PADDED |
4843 HEADERS_FLAG_PRIORITY)) {
4844 EXPECT_CALL(visitor, OnError(_));
4845 } else {
4846 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
4847 EXPECT_CALL(visitor, OnSynStream(57, // stream id
4848 0, // associated stream id
4849 3, // priority
4850 flags & CONTROL_FLAG_FIN,
4851 false)); // unidirectional
4852 } else {
4853 EXPECT_CALL(visitor, OnHeaders(57,
4854 flags & CONTROL_FLAG_FIN,
4855 (flags & HEADERS_FLAG_END_HEADERS) ||
4856 !IsSpdy4()));
4858 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
4859 .WillRepeatedly(testing::Return(true));
4860 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
4861 flags & HEADERS_FLAG_END_HEADERS)) {
4862 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4863 } else {
4864 // Do not close the stream if we are expecting a CONTINUATION frame.
4865 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4869 framer.ProcessInput(frame->data(), frame->size());
4870 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
4871 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4872 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4873 framer.error_code())
4874 << SpdyFramer::ErrorCodeToString(framer.error_code());
4875 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
4876 HEADERS_FLAG_END_HEADERS |
4877 HEADERS_FLAG_END_SEGMENT |
4878 HEADERS_FLAG_PADDED |
4879 HEADERS_FLAG_PRIORITY)) {
4880 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4881 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4882 framer.error_code())
4883 << SpdyFramer::ErrorCodeToString(framer.error_code());
4884 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
4885 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4886 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4887 << SpdyFramer::ErrorCodeToString(framer.error_code());
4888 } else {
4889 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4890 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4891 << SpdyFramer::ErrorCodeToString(framer.error_code());
4896 TEST_P(SpdyFramerTest, PingFrameFlags) {
4897 for (int flags = 0; flags < 256; ++flags) {
4898 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4900 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4901 SpdyFramer framer(spdy_version_);
4902 framer.set_visitor(&visitor);
4904 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
4905 SetFrameFlags(frame.get(), flags, spdy_version_);
4907 if (spdy_version_ > SPDY3 &&
4908 flags == PING_FLAG_ACK) {
4909 EXPECT_CALL(visitor, OnPing(42, true));
4910 } else if (flags == 0) {
4911 EXPECT_CALL(visitor, OnPing(42, false));
4912 } else {
4913 EXPECT_CALL(visitor, OnError(_));
4916 framer.ProcessInput(frame->data(), frame->size());
4917 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
4918 flags == 0) {
4919 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4920 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4921 << SpdyFramer::ErrorCodeToString(framer.error_code());
4922 } else {
4923 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4924 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4925 framer.error_code())
4926 << SpdyFramer::ErrorCodeToString(framer.error_code());
4931 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
4932 for (int flags = 0; flags < 256; ++flags) {
4933 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4935 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4936 SpdyFramer framer(spdy_version_);
4937 framer.set_visitor(&visitor);
4939 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
4940 SpdyWindowUpdateIR(4, 1024)));
4941 SetFrameFlags(frame.get(), flags, spdy_version_);
4943 if (flags != 0) {
4944 EXPECT_CALL(visitor, OnError(_));
4945 } else {
4946 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
4949 framer.ProcessInput(frame->data(), frame->size());
4950 if (flags != 0) {
4951 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4952 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4953 framer.error_code())
4954 << SpdyFramer::ErrorCodeToString(framer.error_code());
4955 } else {
4956 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4957 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4958 << SpdyFramer::ErrorCodeToString(framer.error_code());
4963 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
4964 if (spdy_version_ <= SPDY3) {
4965 return;
4968 for (int flags = 0; flags < 256; ++flags) {
4969 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4971 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
4972 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
4973 SpdyFramer framer(spdy_version_);
4974 framer.set_visitor(&visitor);
4975 framer.set_debug_visitor(&debug_visitor);
4977 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
4979 SpdyPushPromiseIR push_promise(42, 57);
4980 push_promise.SetHeader("foo", "bar");
4981 scoped_ptr<SpdySerializedFrame> frame(
4982 framer.SerializePushPromise(push_promise));
4983 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
4984 // and implement framing.
4985 int set_flags = flags & ~HEADERS_FLAG_PADDED;
4986 SetFrameFlags(frame.get(), set_flags, spdy_version_);
4988 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
4989 EXPECT_CALL(visitor, OnError(_));
4990 } else {
4991 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
4992 EXPECT_CALL(visitor, OnPushPromise(42, 57,
4993 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
4994 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
4995 .WillRepeatedly(testing::Return(true));
4998 framer.ProcessInput(frame->data(), frame->size());
4999 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5000 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5001 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5002 framer.error_code())
5003 << SpdyFramer::ErrorCodeToString(framer.error_code());
5004 } else {
5005 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5006 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5007 << SpdyFramer::ErrorCodeToString(framer.error_code());
5012 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5013 if (spdy_version_ <= SPDY3) {
5014 return;
5017 for (int flags = 0; flags < 256; ++flags) {
5018 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5020 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5021 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5022 SpdyFramer framer(spdy_version_);
5023 framer.set_visitor(&visitor);
5024 framer.set_debug_visitor(&debug_visitor);
5026 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5027 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5028 EXPECT_CALL(visitor, OnHeaders(42, 0, false));
5029 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5030 .WillRepeatedly(testing::Return(true));
5032 SpdyHeadersIR headers_ir(42);
5033 headers_ir.SetHeader("foo", "bar");
5034 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5035 SetFrameFlags(frame0.get(), 0, spdy_version_);
5037 SpdyContinuationIR continuation(42);
5038 continuation.SetHeader("foo", "bar");
5039 scoped_ptr<SpdySerializedFrame> frame(
5040 framer.SerializeContinuation(continuation));
5041 SetFrameFlags(frame.get(), flags, spdy_version_);
5043 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5044 EXPECT_CALL(visitor, OnError(_));
5045 } else {
5046 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5047 EXPECT_CALL(visitor, OnContinuation(42,
5048 flags & HEADERS_FLAG_END_HEADERS));
5049 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5050 .WillRepeatedly(testing::Return(true));
5053 framer.ProcessInput(frame0->data(), frame0->size());
5054 framer.ProcessInput(frame->data(), frame->size());
5055 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5056 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5057 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5058 framer.error_code())
5059 << SpdyFramer::ErrorCodeToString(framer.error_code());
5060 } else {
5061 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5062 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5063 << SpdyFramer::ErrorCodeToString(framer.error_code());
5068 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5070 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5072 TEST_P(SpdyFramerTest, EmptySynStream) {
5073 if (!IsSpdy2() && !IsSpdy3()) {
5074 // SYN_STREAM not supported in SPDY>3.
5075 return;
5077 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5078 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5079 SpdyFramer framer(spdy_version_);
5080 framer.set_visitor(&visitor);
5081 framer.set_debug_visitor(&debug_visitor);
5083 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5085 SpdySynStreamIR syn_stream(1);
5086 syn_stream.set_priority(1);
5087 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5088 // Adjust size to remove the name/value block.
5089 SetFrameLength(
5090 frame.get(),
5091 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5092 spdy_version_);
5094 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5095 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5096 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5098 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5099 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5100 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5101 << SpdyFramer::ErrorCodeToString(framer.error_code());
5104 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5105 const uint32 kId = 0x020304;
5106 const uint32 kFlags = 0x01;
5107 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5109 SettingsFlagsAndId id_and_flags =
5110 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5111 EXPECT_EQ(kId, id_and_flags.id());
5112 EXPECT_EQ(kFlags, id_and_flags.flags());
5113 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5116 // Test handling of a RST_STREAM with out-of-bounds status codes.
5117 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5118 const unsigned char kRstStreamStatusTooLow = 0x00;
5119 const unsigned char kRstStreamStatusTooHigh = 0xff;
5120 const unsigned char kV3RstStreamInvalid[] = {
5121 0x80, spdy_version_ch_, 0x00, 0x03,
5122 0x00, 0x00, 0x00, 0x08,
5123 0x00, 0x00, 0x00, 0x01,
5124 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5126 const unsigned char kV4RstStreamInvalid[] = {
5127 0x00, 0x00, 0x04, 0x03,
5128 0x00, 0x00, 0x00, 0x00,
5129 0x01, 0x00, 0x00, 0x00,
5130 kRstStreamStatusTooLow
5133 const unsigned char kV3RstStreamNumStatusCodes[] = {
5134 0x80, spdy_version_ch_, 0x00, 0x03,
5135 0x00, 0x00, 0x00, 0x08,
5136 0x00, 0x00, 0x00, 0x01,
5137 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5139 const unsigned char kV4RstStreamNumStatusCodes[] = {
5140 0x00, 0x00, 0x04, 0x03,
5141 0x00, 0x00, 0x00, 0x00,
5142 0x01, 0x00, 0x00, 0x00,
5143 kRstStreamStatusTooHigh
5146 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5147 SpdyFramer framer(spdy_version_);
5148 framer.set_visitor(&visitor);
5150 if (IsSpdy4()) {
5151 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5152 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
5153 arraysize(kV4RstStreamInvalid));
5154 } else {
5155 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5156 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5157 arraysize(kV3RstStreamInvalid));
5159 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5160 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5161 << SpdyFramer::ErrorCodeToString(framer.error_code());
5164 framer.Reset();
5166 if (IsSpdy4()) {
5167 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5168 framer.ProcessInput(
5169 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
5170 arraysize(kV4RstStreamNumStatusCodes));
5171 } else {
5172 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5173 framer.ProcessInput(
5174 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5175 arraysize(kV3RstStreamNumStatusCodes));
5177 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5178 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5179 << SpdyFramer::ErrorCodeToString(framer.error_code());
5182 // Test handling of GOAWAY frames with out-of-bounds status code.
5183 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5184 if (spdy_version_ <= SPDY2) {
5185 return;
5187 SpdyFramer framer(spdy_version_);
5189 const unsigned char kV3FrameData[] = {
5190 0x80, spdy_version_ch_, 0x00, 0x07,
5191 0x00, 0x00, 0x00, 0x08,
5192 0x00, 0x00, 0x00, 0x01, // Stream Id
5193 0xff, 0xff, 0xff, 0xff, // Status
5195 const unsigned char kV4FrameData[] = {
5196 0x00, 0x00, 0x0a, 0x07,
5197 0x00, 0x00, 0x00, 0x00,
5198 0x00, 0x00, 0x00, 0x00, // Stream id
5199 0x01, 0xff, 0xff, 0xff, // Status
5200 0xff, 0x47, 0x41, // Opaque Description
5202 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5203 framer.set_visitor(&visitor);
5205 if (IsSpdy3()) {
5206 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5207 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5208 arraysize(kV3FrameData));
5209 } else {
5210 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5211 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5212 arraysize(kV4FrameData));
5214 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5215 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5216 << SpdyFramer::ErrorCodeToString(framer.error_code());
5219 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5220 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5221 const unsigned char kV2FrameData[] = {
5222 0x80, spdy_version_ch_, 0x00, 0x07,
5223 0x00, 0x00, 0x00, 0x04,
5224 0xff, 0xff, 0xff, 0xff,
5226 const unsigned char kV3FrameData[] = {
5227 0x80, spdy_version_ch_, 0x00, 0x07,
5228 0x00, 0x00, 0x00, 0x08,
5229 0xff, 0xff, 0xff, 0xff,
5230 0x00, 0x00, 0x00, 0x00,
5232 const unsigned char kV4FrameData[] = {
5233 0x00, 0x00, 0x08, 0x07,
5234 0x00, 0x00, 0x00, 0x00,
5235 0x00, 0xff, 0xff, 0xff,
5236 0xff, 0x00, 0x00, 0x00,
5237 0x00,
5240 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5241 SpdyFramer framer(spdy_version_);
5242 framer.set_visitor(&visitor);
5244 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5245 if (IsSpdy2()) {
5246 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5247 arraysize(kV2FrameData));
5248 } else if (IsSpdy3()) {
5249 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5250 arraysize(kV3FrameData));
5251 } else {
5252 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5253 arraysize(kV4FrameData));
5255 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5256 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5257 << SpdyFramer::ErrorCodeToString(framer.error_code());
5260 TEST_P(SpdyFramerTest, OnBlocked) {
5261 if (spdy_version_ <= SPDY3) {
5262 return;
5265 const SpdyStreamId kStreamId = 0;
5267 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5268 SpdyFramer framer(spdy_version_);
5269 framer.set_visitor(&visitor);
5271 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5273 SpdyBlockedIR blocked_ir(0);
5274 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5275 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5277 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5278 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5279 << SpdyFramer::ErrorCodeToString(framer.error_code());
5282 TEST_P(SpdyFramerTest, OnAltSvc) {
5283 if (spdy_version_ <= SPDY3) {
5284 return;
5287 const SpdyStreamId kStreamId = 1;
5289 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5290 SpdyFramer framer(spdy_version_);
5291 framer.set_visitor(&visitor);
5293 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5295 443,
5296 StringPiece("pid"),
5297 StringPiece("h1"),
5298 StringPiece("o1")));
5300 SpdyAltSvcIR altsvc_ir(1);
5301 altsvc_ir.set_max_age(10);
5302 altsvc_ir.set_port(443);
5303 altsvc_ir.set_protocol_id("pid");
5304 altsvc_ir.set_host("h1");
5305 altsvc_ir.set_origin("o1");
5306 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5307 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5308 altsvc_ir.protocol_id().length() +
5309 altsvc_ir.host().length() +
5310 altsvc_ir.origin().length());
5312 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5313 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5314 << SpdyFramer::ErrorCodeToString(framer.error_code());
5317 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5318 if (spdy_version_ <= SPDY3) {
5319 return;
5322 const SpdyStreamId kStreamId = 1;
5324 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5325 SpdyFramer framer(spdy_version_);
5326 framer.set_visitor(&visitor);
5328 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5330 443,
5331 StringPiece("pid"),
5332 StringPiece("h1"),
5333 StringPiece("")));
5335 SpdyAltSvcIR altsvc_ir(1);
5336 altsvc_ir.set_max_age(10);
5337 altsvc_ir.set_port(443);
5338 altsvc_ir.set_protocol_id("pid");
5339 altsvc_ir.set_host("h1");
5340 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5341 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5342 altsvc_ir.protocol_id().length() +
5343 altsvc_ir.host().length());
5345 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5346 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5347 << SpdyFramer::ErrorCodeToString(framer.error_code());
5350 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5351 if (spdy_version_ <= SPDY3) {
5352 return;
5355 const unsigned char kType = static_cast<unsigned char>(
5356 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
5358 TestSpdyVisitor visitor(spdy_version_);
5359 SpdyFramer framer(spdy_version_);
5360 framer.set_visitor(&visitor);
5362 const unsigned char kFrameDataLargePIDLen[] = {
5363 0x00, 0x00, 0x17, kType, 0x00,
5364 0x00, 0x00, 0x00, 0x03,
5365 0x00, 0x00, 0x00, 0x05,
5366 0x01, 0xbb, 0x00, 0x05, // Port = 443
5367 'p', 'i', 'd', '1', // Protocol-ID
5368 0x04, 'h', 'o', 's',
5369 't', 'o', 'r', 'i',
5370 'g', 'i', 'n',
5373 visitor.SimulateInFramer(kFrameDataLargePIDLen,
5374 sizeof(kFrameDataLargePIDLen));
5375 EXPECT_EQ(1, visitor.error_count_);
5376 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5377 visitor.framer_.error_code());
5381 TestSpdyVisitor visitor(spdy_version_);
5382 SpdyFramer framer(spdy_version_);
5383 framer.set_visitor(&visitor);
5384 const unsigned char kFrameDataPIDLenLargerThanFrame[] = {
5385 0x00, 0x00, 0x17, kType, 0x00,
5386 0x00, 0x00, 0x00, 0x03,
5387 0x00, 0x00, 0x00, 0x05,
5388 0x01, 0xbb, 0x00, 0x99, // Port = 443
5389 'p', 'i', 'd', '1', // Protocol-ID
5390 0x04, 'h', 'o', 's',
5391 't', 'o', 'r', 'i',
5392 'g', 'i', 'n',
5395 visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame,
5396 sizeof(kFrameDataPIDLenLargerThanFrame));
5397 EXPECT_EQ(1, visitor.error_count_);
5398 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5399 visitor.framer_.error_code());
5403 TestSpdyVisitor visitor(spdy_version_);
5404 SpdyFramer framer(spdy_version_);
5405 framer.set_visitor(&visitor);
5407 const unsigned char kFrameDataLargeHostLen[] = {
5408 0x00, 0x00, 0x17, kType, 0x00,
5409 0x00, 0x00, 0x00, 0x03,
5410 0x00, 0x00, 0x00, 0x05,
5411 0x01, 0xbb, 0x00, 0x04, // Port = 443
5412 'p', 'i', 'd', '1', // Protocol-ID
5413 0x0f, 'h', 'o', 's',
5414 't', 'o', 'r', 'i',
5415 'g', 'i', 'n',
5418 visitor.SimulateInFramer(kFrameDataLargeHostLen,
5419 sizeof(kFrameDataLargeHostLen));
5420 EXPECT_EQ(1, visitor.error_count_);
5421 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5422 visitor.framer_.error_code());
5426 TestSpdyVisitor visitor(spdy_version_);
5427 SpdyFramer framer(spdy_version_);
5428 framer.set_visitor(&visitor);
5429 const unsigned char kFrameDataSmallPIDLen[] = {
5430 0x00, 0x00, 0x17, kType, 0x00,
5431 0x00, 0x00, 0x00, 0x03,
5432 0x00, 0x00, 0x00, 0x05,
5433 0x01, 0xbb, 0x00, 0x01, // Port = 443
5434 'p', 'i', 'd', '1', // Protocol-ID
5435 0x04, 'h', 'o', 's',
5436 't', 'o', 'r', 'i',
5437 'g', 'i', 'n',
5440 visitor.SimulateInFramer(kFrameDataSmallPIDLen,
5441 sizeof(kFrameDataSmallPIDLen));
5442 EXPECT_EQ(1, visitor.error_count_);
5443 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5444 visitor.framer_.error_code());
5448 // Tests handling of ALTSVC frames delivered in small chunks.
5449 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5450 if (spdy_version_ <= SPDY3) {
5451 return;
5453 SpdyFramer framer(spdy_version_);
5454 SpdyAltSvcIR altsvc_ir(1);
5455 altsvc_ir.set_max_age(20);
5456 altsvc_ir.set_port(443);
5457 altsvc_ir.set_protocol_id("protocolid");
5458 altsvc_ir.set_host("hostname");
5460 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5461 TestSpdyVisitor visitor(spdy_version_);
5462 visitor.use_compression_ = false;
5464 // Read data in small chunks.
5465 size_t framed_data = 0;
5466 size_t unframed_data = control_frame->size();
5467 size_t kReadChunkSize = 5; // Read five bytes at a time.
5468 while (unframed_data > 0) {
5469 size_t to_read = min(kReadChunkSize, unframed_data);
5470 visitor.SimulateInFramer(
5471 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5472 to_read);
5473 unframed_data -= to_read;
5474 framed_data += to_read;
5476 EXPECT_EQ(0, visitor.error_count_);
5477 EXPECT_EQ(1, visitor.altsvc_count_);
5478 EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
5479 EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
5480 EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
5481 EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
5484 // Tests handling of PRIORITY frames.
5485 TEST_P(SpdyFramerTest, ReadPriority) {
5486 if (spdy_version_ <= SPDY3) {
5487 return;
5489 SpdyFramer framer(spdy_version_);
5490 SpdyPriorityIR priority(3, 1, 255, false);
5491 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5492 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5493 framer.set_visitor(&visitor);
5494 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5495 framer.ProcessInput(frame->data(), frame->size());
5497 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5498 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5499 << SpdyFramer::ErrorCodeToString(framer.error_code());
5500 // TODO(mlavan): once we actually maintain a priority tree,
5501 // check that state is adjusted correctly.
5504 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5505 if (spdy_version_ <= SPDY3) {
5506 return;
5508 SpdyFramer framer(spdy_version_);
5510 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5511 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5512 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5513 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5514 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5515 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5516 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5517 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5519 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5520 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5521 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5522 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5523 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5524 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5525 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5526 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5527 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5528 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5529 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5530 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5531 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5532 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5533 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5536 // Tests handling of PRIORITY frame with incorrect size.
5537 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5538 if (spdy_version_ <= SPDY3) {
5539 return;
5542 // PRIORITY frame of size 4, which isn't correct.
5543 const unsigned char kFrameData[] = {
5544 0x00, 0x00, 0x04, 0x02, 0x00,
5545 0x00, 0x00, 0x00, 0x03,
5546 0x00, 0x00, 0x00, 0x01,
5549 TestSpdyVisitor visitor(spdy_version_);
5550 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
5552 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
5553 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5554 visitor.framer_.error_code())
5555 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
5558 } // namespace net