Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blobdbf27a03d8a546b299c76ad9bf78eaaa47be16e5
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 std::string;
22 using testing::_;
24 namespace net {
26 namespace test {
28 static const size_t kMaxDecompressedSize = 1024;
30 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
31 public:
32 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
33 SpdyFrameType type,
34 size_t payload_len,
35 size_t frame_len));
37 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
38 SpdyFrameType type,
39 size_t frame_len));
42 class SpdyFramerTestUtil {
43 public:
44 // Decompress a single frame using the decompression context held by
45 // the SpdyFramer. The implemention is meant for use only in tests
46 // and will CHECK fail if the input is anything other than a single,
47 // well-formed compressed frame.
49 // Returns a new decompressed SpdyFrame.
50 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
51 SpdyFramer* framer, const SpdyFrameType& frame) {
52 DecompressionVisitor visitor(framer->protocol_version());
53 framer->set_visitor(&visitor);
54 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
55 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
56 framer->set_visitor(NULL);
58 char* buffer = visitor.ReleaseBuffer();
59 CHECK(buffer != NULL);
60 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
61 SetFrameLength(decompressed_frame,
62 visitor.size() - framer->GetControlFrameHeaderSize(),
63 framer->protocol_version());
64 return decompressed_frame;
67 class DecompressionVisitor : public SpdyFramerVisitorInterface {
68 public:
69 explicit DecompressionVisitor(SpdyMajorVersion version)
70 : version_(version), size_(0), finished_(false) {}
72 void ResetBuffer() {
73 CHECK(buffer_.get() == NULL);
74 CHECK_EQ(0u, size_);
75 CHECK(!finished_);
76 buffer_.reset(new char[kMaxDecompressedSize]);
79 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
80 void OnDataFrameHeader(SpdyStreamId stream_id,
81 size_t length,
82 bool fin) override {
83 LOG(FATAL) << "Unexpected data frame header";
85 void OnStreamFrameData(SpdyStreamId stream_id,
86 const char* data,
87 size_t len,
88 bool fin) override {
89 LOG(FATAL);
92 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
93 LOG(FATAL);
96 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
97 const char* header_data,
98 size_t len) override {
99 CHECK(buffer_.get() != NULL);
100 CHECK_GE(kMaxDecompressedSize, size_ + len);
101 CHECK(!finished_);
102 if (len != 0) {
103 memcpy(buffer_.get() + size_, header_data, len);
104 size_ += len;
105 } else {
106 // Done.
107 finished_ = true;
109 return true;
112 void OnSynStream(SpdyStreamId stream_id,
113 SpdyStreamId associated_stream_id,
114 SpdyPriority priority,
115 bool fin,
116 bool unidirectional) override {
117 SpdyFramer framer(version_);
118 framer.set_enable_compression(false);
119 SpdySynStreamIR syn_stream(stream_id);
120 syn_stream.set_associated_to_stream_id(associated_stream_id);
121 syn_stream.set_priority(priority);
122 syn_stream.set_fin(fin);
123 syn_stream.set_unidirectional(unidirectional);
124 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
125 ResetBuffer();
126 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
127 size_ += framer.GetSynStreamMinimumSize();
130 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
131 SpdyFramer framer(version_);
132 framer.set_enable_compression(false);
133 SpdyHeadersIR headers(stream_id);
134 headers.set_fin(fin);
135 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
136 ResetBuffer();
137 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
138 size_ += framer.GetSynStreamMinimumSize();
141 void OnRstStream(SpdyStreamId stream_id,
142 SpdyRstStreamStatus status) override {
143 LOG(FATAL);
145 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
146 LOG(FATAL);
148 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
149 void OnSettingsEnd() override { LOG(FATAL); }
150 void OnGoAway(SpdyStreamId last_accepted_stream_id,
151 SpdyGoAwayStatus status) override {
152 LOG(FATAL);
155 void OnHeaders(SpdyStreamId stream_id,
156 bool has_priority,
157 SpdyPriority priority,
158 SpdyStreamId parent_stream_id,
159 bool exclusive,
160 bool fin,
161 bool end) override {
162 SpdyFramer framer(version_);
163 framer.set_enable_compression(false);
164 SpdyHeadersIR headers(stream_id);
165 headers.set_has_priority(has_priority);
166 headers.set_priority(priority);
167 headers.set_parent_stream_id(parent_stream_id);
168 headers.set_exclusive(exclusive);
169 headers.set_fin(fin);
170 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
171 ResetBuffer();
172 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
173 size_ += framer.GetHeadersMinimumSize();
176 void OnWindowUpdate(SpdyStreamId stream_id,
177 int delta_window_size) override {
178 LOG(FATAL);
181 void OnPushPromise(SpdyStreamId stream_id,
182 SpdyStreamId promised_stream_id,
183 bool end) override {
184 SpdyFramer framer(version_);
185 framer.set_enable_compression(false);
186 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
187 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
188 ResetBuffer();
189 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
190 size_ += framer.GetPushPromiseMinimumSize();
193 void OnContinuation(SpdyStreamId stream_id, bool end) override {
194 LOG(FATAL);
197 void OnPriority(SpdyStreamId stream_id,
198 SpdyStreamId parent_stream_id,
199 uint8 weight,
200 bool exclusive) override {
201 // Do nothing.
204 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
205 LOG(FATAL);
206 return false;
209 char* ReleaseBuffer() {
210 CHECK(finished_);
211 return buffer_.release();
214 size_t size() const {
215 CHECK(finished_);
216 return size_;
219 private:
220 SpdyMajorVersion version_;
221 scoped_ptr<char[]> buffer_;
222 size_t size_;
223 bool finished_;
225 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
228 private:
229 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
232 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
233 public SpdyFramerDebugVisitorInterface {
234 public:
235 // This is larger than our max frame size because header blocks that
236 // are too long can spill over into CONTINUATION frames.
237 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
239 explicit TestSpdyVisitor(SpdyMajorVersion version)
240 : framer_(version),
241 use_compression_(false),
242 error_count_(0),
243 syn_frame_count_(0),
244 syn_reply_frame_count_(0),
245 headers_frame_count_(0),
246 push_promise_frame_count_(0),
247 goaway_count_(0),
248 setting_count_(0),
249 settings_ack_sent_(0),
250 settings_ack_received_(0),
251 continuation_count_(0),
252 altsvc_count_(0),
253 priority_count_(0),
254 test_altsvc_ir_(0),
255 on_unknown_frame_result_(false),
256 last_window_update_stream_(0),
257 last_window_update_delta_(0),
258 last_push_promise_stream_(0),
259 last_push_promise_promised_stream_(0),
260 data_bytes_(0),
261 fin_frame_count_(0),
262 fin_opaque_data_(),
263 fin_flag_count_(0),
264 zero_length_data_frame_count_(0),
265 control_frame_header_data_count_(0),
266 zero_length_control_frame_header_data_count_(0),
267 data_frame_count_(0),
268 last_payload_len_(0),
269 last_frame_len_(0),
270 header_buffer_(new char[kDefaultHeaderBufferSize]),
271 header_buffer_length_(0),
272 header_buffer_size_(kDefaultHeaderBufferSize),
273 header_stream_id_(static_cast<SpdyStreamId>(-1)),
274 header_control_type_(DATA),
275 header_buffer_valid_(false) {}
277 void OnError(SpdyFramer* f) override {
278 LOG(INFO) << "SpdyFramer Error: "
279 << SpdyFramer::ErrorCodeToString(f->error_code());
280 ++error_count_;
283 void OnDataFrameHeader(SpdyStreamId stream_id,
284 size_t length,
285 bool fin) override {
286 ++data_frame_count_;
287 header_stream_id_ = stream_id;
290 void OnStreamFrameData(SpdyStreamId stream_id,
291 const char* data,
292 size_t len,
293 bool fin) override {
294 EXPECT_EQ(header_stream_id_, stream_id);
295 if (len == 0)
296 ++zero_length_data_frame_count_;
298 data_bytes_ += len;
299 LOG(INFO) << "OnStreamFrameData(" << stream_id << ", \"";
300 if (len > 0) {
301 for (size_t i = 0 ; i < len; ++i) {
302 LOG(INFO) << std::hex << (0xFF & static_cast<unsigned int>(data[i]))
303 << std::dec;
306 LOG(INFO) << "\", " << len << ")\n";
309 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
310 EXPECT_EQ(header_stream_id_, stream_id);
311 data_bytes_ += len;
312 LOG(INFO) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
315 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
316 const char* header_data,
317 size_t len) override {
318 ++control_frame_header_data_count_;
319 CHECK_EQ(header_stream_id_, stream_id);
320 if (len == 0) {
321 ++zero_length_control_frame_header_data_count_;
322 // Indicates end-of-header-block.
323 headers_.clear();
324 CHECK(header_buffer_valid_);
325 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
326 header_buffer_.get(), header_buffer_length_, &headers_);
327 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
328 << "Check failed: header_buffer_length_ == parsed_length "
329 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
330 return true;
332 const size_t available = header_buffer_size_ - header_buffer_length_;
333 if (len > available) {
334 header_buffer_valid_ = false;
335 return false;
337 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
338 header_buffer_length_ += len;
339 return true;
342 void OnSynStream(SpdyStreamId stream_id,
343 SpdyStreamId associated_stream_id,
344 SpdyPriority priority,
345 bool fin,
346 bool unidirectional) override {
347 ++syn_frame_count_;
348 if (framer_.protocol_version() > SPDY3) {
349 InitHeaderStreaming(HEADERS, stream_id);
350 } else {
351 InitHeaderStreaming(SYN_STREAM, stream_id);
353 if (fin) {
354 ++fin_flag_count_;
358 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
359 ++syn_reply_frame_count_;
360 if (framer_.protocol_version() > SPDY3) {
361 InitHeaderStreaming(HEADERS, stream_id);
362 } else {
363 InitHeaderStreaming(SYN_REPLY, stream_id);
365 if (fin) {
366 ++fin_flag_count_;
370 void OnRstStream(SpdyStreamId stream_id,
371 SpdyRstStreamStatus status) override {
372 ++fin_frame_count_;
375 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
376 if ((rst_stream_data != NULL) && (len > 0)) {
377 fin_opaque_data_ += string(rst_stream_data, len);
379 return true;
382 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
383 ++setting_count_;
386 void OnSettingsAck() override {
387 DCHECK_LT(SPDY3, framer_.protocol_version());
388 ++settings_ack_received_;
391 void OnSettingsEnd() override {
392 if (framer_.protocol_version() <= SPDY3) { return; }
393 ++settings_ack_sent_;
396 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
398 void OnGoAway(SpdyStreamId last_accepted_stream_id,
399 SpdyGoAwayStatus status) override {
400 ++goaway_count_;
403 void OnHeaders(SpdyStreamId stream_id,
404 bool has_priority,
405 SpdyPriority priority,
406 SpdyStreamId parent_stream_id,
407 bool exclusive,
408 bool fin,
409 bool end) override {
410 ++headers_frame_count_;
411 InitHeaderStreaming(HEADERS, stream_id);
412 if (fin) {
413 ++fin_flag_count_;
415 header_has_priority_ = has_priority;
416 header_parent_stream_id_ = parent_stream_id;
417 header_exclusive_ = exclusive;
420 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
421 last_window_update_stream_ = stream_id;
422 last_window_update_delta_ = delta_window_size;
425 void OnPushPromise(SpdyStreamId stream_id,
426 SpdyStreamId promised_stream_id,
427 bool end) override {
428 ++push_promise_frame_count_;
429 InitHeaderStreaming(PUSH_PROMISE, stream_id);
430 last_push_promise_stream_ = stream_id;
431 last_push_promise_promised_stream_ = promised_stream_id;
434 void OnContinuation(SpdyStreamId stream_id, bool end) override {
435 ++continuation_count_;
438 void OnAltSvc(SpdyStreamId stream_id,
439 StringPiece origin,
440 const SpdyAltSvcWireFormat::AlternativeServiceVector&
441 altsvc_vector) override {
442 test_altsvc_ir_.set_stream_id(stream_id);
443 if (origin.length() > 0) {
444 test_altsvc_ir_.set_origin(origin.as_string());
446 for (const SpdyAltSvcWireFormat::AlternativeService& altsvc :
447 altsvc_vector) {
448 test_altsvc_ir_.add_altsvc(altsvc);
450 ++altsvc_count_;
453 void OnPriority(SpdyStreamId stream_id,
454 SpdyStreamId parent_stream_id,
455 uint8 weight,
456 bool exclusive) override {
457 ++priority_count_;
460 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
461 DLOG(INFO) << "Unknown frame type " << frame_type;
462 return on_unknown_frame_result_;
465 void OnSendCompressedFrame(SpdyStreamId stream_id,
466 SpdyFrameType type,
467 size_t payload_len,
468 size_t frame_len) override {
469 last_payload_len_ = payload_len;
470 last_frame_len_ = frame_len;
473 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
474 SpdyFrameType type,
475 size_t frame_len) override {
476 last_frame_len_ = frame_len;
479 // Convenience function which runs a framer simulation with particular input.
480 void SimulateInFramer(const unsigned char* input, size_t size) {
481 framer_.set_enable_compression(use_compression_);
482 framer_.set_visitor(this);
483 size_t input_remaining = size;
484 const char* input_ptr = reinterpret_cast<const char*>(input);
485 while (input_remaining > 0 &&
486 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
487 // To make the tests more interesting, we feed random (amd small) chunks
488 // into the framer. This simulates getting strange-sized reads from
489 // the socket.
490 const size_t kMaxReadSize = 32;
491 size_t bytes_read =
492 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
493 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
494 input_remaining -= bytes_processed;
495 input_ptr += bytes_processed;
499 void InitHeaderStreaming(SpdyFrameType header_control_type,
500 SpdyStreamId stream_id) {
501 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
502 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
503 header_control_type))) {
504 DLOG(FATAL) << "Attempted to init header streaming with "
505 << "invalid control frame type: "
506 << header_control_type;
508 memset(header_buffer_.get(), 0, header_buffer_size_);
509 header_buffer_length_ = 0;
510 header_stream_id_ = stream_id;
511 header_control_type_ = header_control_type;
512 header_buffer_valid_ = true;
513 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
516 // Override the default buffer size (16K). Call before using the framer!
517 void set_header_buffer_size(size_t header_buffer_size) {
518 header_buffer_size_ = header_buffer_size;
519 header_buffer_.reset(new char[header_buffer_size]);
522 // Largest control frame that the SPDY implementation sends, including the
523 // size of the header.
524 static size_t sent_control_frame_max_size() {
525 return SpdyFramer::kMaxControlFrameSize;
528 static size_t header_data_chunk_max_size() {
529 return SpdyFramer::kHeaderDataChunkMaxSize;
532 SpdyFramer framer_;
533 bool use_compression_;
535 // Counters from the visitor callbacks.
536 int error_count_;
537 int syn_frame_count_;
538 int syn_reply_frame_count_;
539 int headers_frame_count_;
540 int push_promise_frame_count_;
541 int goaway_count_;
542 int setting_count_;
543 int settings_ack_sent_;
544 int settings_ack_received_;
545 int continuation_count_;
546 int altsvc_count_;
547 int priority_count_;
548 SpdyAltSvcIR test_altsvc_ir_;
549 bool on_unknown_frame_result_;
550 SpdyStreamId last_window_update_stream_;
551 int last_window_update_delta_;
552 SpdyStreamId last_push_promise_stream_;
553 SpdyStreamId last_push_promise_promised_stream_;
554 int data_bytes_;
555 int fin_frame_count_; // The count of RST_STREAM type frames received.
556 string fin_opaque_data_;
557 int fin_flag_count_; // The count of frames with the FIN flag set.
558 int zero_length_data_frame_count_; // The count of zero-length data frames.
559 int control_frame_header_data_count_; // The count of chunks received.
560 // The count of zero-length control frame header data chunks received.
561 int zero_length_control_frame_header_data_count_;
562 int data_frame_count_;
563 size_t last_payload_len_;
564 size_t last_frame_len_;
566 // Header block streaming state:
567 scoped_ptr<char[]> header_buffer_;
568 size_t header_buffer_length_;
569 size_t header_buffer_size_;
570 SpdyStreamId header_stream_id_;
571 SpdyFrameType header_control_type_;
572 bool header_buffer_valid_;
573 SpdyHeaderBlock headers_;
574 bool header_has_priority_;
575 SpdyStreamId header_parent_stream_id_;
576 bool header_exclusive_;
579 class SpdyFramerPeer {
580 public:
581 static size_t ControlFrameBufferSize() {
582 return SpdyFramer::kControlFrameBufferSize;
584 static size_t GetNumberRequiredContinuationFrames(SpdyFramer* framer,
585 size_t size) {
586 return framer->GetNumberRequiredContinuationFrames(size);
590 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
591 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
592 const SpdyFramer& framer) {
593 SpdyFrameReader reader(frame->data(), frame->size());
594 if (framer.protocol_version() > SPDY3) {
595 reader.Seek(3); // Seek past the frame length.
596 } else {
597 reader.Seek(2); // Seek past the frame length.
599 SpdyFrameType frame_type;
600 if (framer.protocol_version() > SPDY3) {
601 uint8 serialized_type;
602 reader.ReadUInt8(&serialized_type);
603 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
604 serialized_type);
605 DCHECK_EQ(HEADERS, frame_type);
606 uint8 flags;
607 reader.ReadUInt8(&flags);
608 if (flags & HEADERS_FLAG_PRIORITY) {
609 frame_type = SYN_STREAM;
611 } else {
612 uint16 serialized_type;
613 reader.ReadUInt16(&serialized_type);
614 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
615 serialized_type);
616 DCHECK(frame_type == HEADERS ||
617 frame_type == SYN_STREAM) << frame_type;
620 if (frame_type == SYN_STREAM) {
621 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
622 frame->size() - framer.GetSynStreamMinimumSize());
623 } else {
624 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
625 frame->size() - framer.GetHeadersMinimumSize());
629 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
630 protected:
631 void SetUp() override {
632 spdy_version_ = GetParam();
633 spdy_version_ch_ = static_cast<unsigned char>(
634 SpdyConstants::SerializeMajorVersion(spdy_version_));
637 void CompareFrame(const string& description,
638 const SpdyFrame& actual_frame,
639 const unsigned char* expected,
640 const int expected_len) {
641 const unsigned char* actual =
642 reinterpret_cast<const unsigned char*>(actual_frame.data());
643 CompareCharArraysWithHexError(
644 description, actual, actual_frame.size(), expected, expected_len);
647 void CompareFrames(const string& description,
648 const SpdyFrame& expected_frame,
649 const SpdyFrame& actual_frame) {
650 CompareCharArraysWithHexError(
651 description,
652 reinterpret_cast<const unsigned char*>(expected_frame.data()),
653 expected_frame.size(),
654 reinterpret_cast<const unsigned char*>(actual_frame.data()),
655 actual_frame.size());
658 // Returns true if the two header blocks have equivalent content.
659 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
660 const SpdyHeaderBlock* actual) {
661 if (expected->size() != actual->size()) {
662 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
663 << actual->size() << ".";
664 return false;
666 for (SpdyHeaderBlock::const_iterator it = expected->begin();
667 it != expected->end();
668 ++it) {
669 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
670 if (it2 == actual->end()) {
671 LOG(ERROR) << "Expected header name '" << it->first << "'.";
672 return false;
674 if (it->second.compare(it2->second) != 0) {
675 LOG(ERROR) << "Expected header named '" << it->first
676 << "' to have a value of '" << it->second
677 << "'. The actual value received was '" << it2->second
678 << "'.";
679 return false;
682 return true;
685 bool IsSpdy2() { return spdy_version_ == SPDY2; }
686 bool IsSpdy3() { return spdy_version_ == SPDY3; }
687 bool IsHttp2() { return spdy_version_ == HTTP2; }
689 // Version of SPDY protocol to be used.
690 SpdyMajorVersion spdy_version_;
691 unsigned char spdy_version_ch_;
694 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, HTTP/2.
695 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
696 SpdyFramerTest,
697 ::testing::Values(SPDY2, SPDY3, HTTP2));
699 // Test that we ignore cookie where both name and value are empty.
700 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
701 if (spdy_version_ > SPDY3) {
702 // Not implemented for hpack.
703 return;
706 SpdyFramer framer(spdy_version_);
707 framer.set_enable_compression(true);
708 SpdyHeadersIR headers(1);
709 headers.set_priority(1);
710 headers.SetHeader("cookie",
711 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
712 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
713 EXPECT_TRUE(frame.get() != NULL);
715 TestSpdyVisitor visitor(spdy_version_);
716 visitor.use_compression_ = true;
717 visitor.SimulateInFramer(
718 reinterpret_cast<unsigned char*>(frame->data()),
719 frame->size());
721 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
722 EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
723 &visitor.headers_));
724 EXPECT_EQ(1u, visitor.headers_.size());
725 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
728 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
729 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
730 SpdyFramer framer(spdy_version_);
731 framer.set_enable_compression(false);
733 // Encode the header block into a Headers frame.
734 SpdyHeadersIR headers(1);
735 headers.set_priority(1);
736 headers.SetHeader("alpha", "beta");
737 headers.SetHeader("gamma", "charlie");
738 headers.SetHeader("cookie", "key1=value1; key2=value2");
739 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
740 EXPECT_TRUE(frame.get() != NULL);
742 TestSpdyVisitor visitor(spdy_version_);
743 visitor.use_compression_ = false;
744 visitor.SimulateInFramer(
745 reinterpret_cast<unsigned char*>(frame->data()),
746 frame->size());
748 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
749 EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
750 &visitor.headers_));
753 // Test that if there's not a full frame, we fail to parse it.
754 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
755 SpdyFramer framer(spdy_version_);
756 framer.set_enable_compression(false);
758 // Encode the header block into a Headers frame.
759 SpdyHeadersIR headers(1);
760 headers.set_priority(1);
761 headers.SetHeader("alpha", "beta");
762 headers.SetHeader("gamma", "charlie");
763 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
764 EXPECT_TRUE(frame.get() != NULL);
766 TestSpdyVisitor visitor(spdy_version_);
767 visitor.use_compression_ = false;
768 visitor.SimulateInFramer(
769 reinterpret_cast<unsigned char*>(frame->data()),
770 frame->size() - 2);
772 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
773 EXPECT_EQ(0u, visitor.headers_.size());
776 // Test that we can encode and decode stream dependency values in a header
777 // frame.
778 TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
779 if (spdy_version_ <= SPDY3) {
780 return;
782 SpdyFramer framer(spdy_version_);
783 framer.set_enable_compression(false);
785 const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
786 for (SpdyStreamId parent_stream_id : parent_stream_id_test_array) {
787 const bool exclusive_test_array[] = {true, false};
788 for (bool exclusive : exclusive_test_array) {
789 SpdyHeadersIR headers(1);
790 headers.set_has_priority(true);
791 headers.set_parent_stream_id(parent_stream_id);
792 headers.set_exclusive(exclusive);
793 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
794 EXPECT_TRUE(frame.get() != NULL);
796 TestSpdyVisitor visitor(spdy_version_);
797 visitor.use_compression_ = false;
798 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame->data()),
799 frame->size());
801 EXPECT_TRUE(visitor.header_has_priority_);
802 EXPECT_EQ(parent_stream_id, visitor.header_parent_stream_id_);
803 EXPECT_EQ(exclusive, visitor.header_exclusive_);
808 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
809 // (but don't crash).
810 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
811 if (spdy_version_ > SPDY3) {
812 return;
814 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
815 SpdyFramer framer(spdy_version_);
816 framer.set_visitor(&visitor);
818 SpdySynReplyIR syn_reply(0);
819 syn_reply.SetHeader("alpha", "beta");
820 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
821 ASSERT_TRUE(frame.get() != NULL);
823 // We shouldn't have to read the whole frame before we signal an error.
824 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
825 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
826 EXPECT_TRUE(framer.HasError());
827 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
828 << SpdyFramer::ErrorCodeToString(framer.error_code());
831 // Test that if we receive a HEADERS with stream ID zero, we signal an error
832 // (but don't crash).
833 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
834 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
835 SpdyFramer framer(spdy_version_);
836 framer.set_visitor(&visitor);
838 SpdyHeadersIR headers_ir(0);
839 headers_ir.SetHeader("alpha", "beta");
840 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
841 ASSERT_TRUE(frame.get() != NULL);
843 // We shouldn't have to read the whole frame before we signal an error.
844 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
845 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
846 EXPECT_TRUE(framer.HasError());
847 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
848 << SpdyFramer::ErrorCodeToString(framer.error_code());
851 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
852 // error (but don't crash).
853 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
854 if (spdy_version_ <= SPDY3) {
855 return;
858 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
859 SpdyFramer framer(spdy_version_);
860 framer.set_visitor(&visitor);
862 SpdyPushPromiseIR push_promise(0, 4);
863 push_promise.SetHeader("alpha", "beta");
864 scoped_ptr<SpdySerializedFrame> frame(
865 framer.SerializePushPromise(push_promise));
866 ASSERT_TRUE(frame.get() != NULL);
868 // We shouldn't have to read the whole frame before we signal an error.
869 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
870 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
871 EXPECT_TRUE(framer.HasError());
872 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
873 << SpdyFramer::ErrorCodeToString(framer.error_code());
876 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
877 // signal an error (but don't crash).
878 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
879 if (spdy_version_ <= SPDY3) {
880 return;
883 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
884 SpdyFramer framer(spdy_version_);
885 framer.set_visitor(&visitor);
887 SpdyPushPromiseIR push_promise(3, 0);
888 push_promise.SetHeader("alpha", "beta");
889 scoped_ptr<SpdySerializedFrame> frame(
890 framer.SerializePushPromise(push_promise));
891 ASSERT_TRUE(frame.get() != NULL);
893 // We shouldn't have to read the whole frame before we signal an error.
894 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
895 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
896 EXPECT_TRUE(framer.HasError());
897 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
898 << SpdyFramer::ErrorCodeToString(framer.error_code());
901 TEST_P(SpdyFramerTest, DuplicateHeader) {
902 if (spdy_version_ > SPDY3) {
903 // TODO(jgraettinger): Punting on this because we haven't determined
904 // whether duplicate HPACK headers other than Cookie are an error.
905 // If they are, this will need to be updated to use HpackOutputStream.
906 return;
908 SpdyFramer framer(spdy_version_);
909 // Frame builder with plentiful buffer size.
910 SpdyFrameBuilder frame(1024, spdy_version_);
911 if (spdy_version_ <= SPDY3) {
912 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
913 frame.WriteUInt32(3); // stream_id
914 frame.WriteUInt32(0); // associated stream id
915 frame.WriteUInt16(0); // Priority.
916 } else {
917 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
918 frame.WriteUInt32(framer.GetHighestPriority());
921 if (IsSpdy2()) {
922 frame.WriteUInt16(2); // Number of headers.
923 frame.WriteStringPiece16("name");
924 frame.WriteStringPiece16("value1");
925 frame.WriteStringPiece16("name");
926 frame.WriteStringPiece16("value2");
927 } else {
928 frame.WriteUInt32(2); // Number of headers.
929 frame.WriteStringPiece32("name");
930 frame.WriteStringPiece32("value1");
931 frame.WriteStringPiece32("name");
932 frame.WriteStringPiece32("value2");
934 // write the length
935 frame.RewriteLength(framer);
937 SpdyHeaderBlock new_headers;
938 framer.set_enable_compression(false);
939 scoped_ptr<SpdyFrame> control_frame(frame.take());
940 base::StringPiece serialized_headers =
941 GetSerializedHeaders(control_frame.get(), framer);
942 // This should fail because duplicate headers are verboten by the spec.
943 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
944 serialized_headers.size(),
945 &new_headers));
948 TEST_P(SpdyFramerTest, MultiValueHeader) {
949 SpdyFramer framer(spdy_version_);
950 // Frame builder with plentiful buffer size.
951 SpdyFrameBuilder frame(1024, spdy_version_);
952 if (spdy_version_ <= SPDY3) {
953 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
954 frame.WriteUInt32(3); // stream_id
955 frame.WriteUInt32(0); // associated stream id
956 frame.WriteUInt16(0); // Priority.
957 } else {
958 frame.BeginNewFrame(framer,
959 HEADERS,
960 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
962 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
963 frame.WriteUInt8(255); // Priority weight.
966 string value("value1\0value2", 13);
967 if (IsSpdy2()) {
968 frame.WriteUInt16(1); // Number of headers.
969 frame.WriteStringPiece16("name");
970 frame.WriteStringPiece16(value);
971 } else if (spdy_version_ > SPDY3) {
972 // TODO(jgraettinger): If this pattern appears again, move to test class.
973 std::map<string, string> header_set;
974 header_set["name"] = value;
975 string buffer;
976 HpackEncoder encoder(ObtainHpackHuffmanTable());
977 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
978 frame.WriteBytes(&buffer[0], buffer.size());
979 } else {
980 frame.WriteUInt32(1); // Number of headers.
981 frame.WriteStringPiece32("name");
982 frame.WriteStringPiece32(value);
984 // write the length
985 frame.RewriteLength(framer);
987 framer.set_enable_compression(false);
988 scoped_ptr<SpdyFrame> control_frame(frame.take());
990 TestSpdyVisitor visitor(spdy_version_);
991 visitor.use_compression_ = false;
992 visitor.SimulateInFramer(
993 reinterpret_cast<unsigned char*>(control_frame->data()),
994 control_frame->size());
996 EXPECT_THAT(visitor.headers_,
997 testing::ElementsAre(testing::Pair("name", value)));
1000 TEST_P(SpdyFramerTest, BasicCompression) {
1001 if (spdy_version_ > SPDY3) {
1002 // Deflate compression doesn't apply to HPACK.
1003 return;
1005 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
1006 SpdyFramer framer(spdy_version_);
1007 framer.set_debug_visitor(visitor.get());
1008 SpdySynStreamIR syn_stream(1);
1009 syn_stream.set_priority(1);
1010 syn_stream.SetHeader("server", "SpdyServer 1.0");
1011 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1012 syn_stream.SetHeader("status", "200");
1013 syn_stream.SetHeader("version", "HTTP/1.1");
1014 syn_stream.SetHeader("content-type", "text/html");
1015 syn_stream.SetHeader("content-length", "12");
1016 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
1017 size_t uncompressed_size1 = visitor->last_payload_len_;
1018 size_t compressed_size1 =
1019 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1020 if (IsSpdy2()) {
1021 EXPECT_EQ(139u, uncompressed_size1);
1022 #if defined(USE_SYSTEM_ZLIB)
1023 EXPECT_EQ(155u, compressed_size1);
1024 #else // !defined(USE_SYSTEM_ZLIB)
1025 EXPECT_EQ(135u, compressed_size1);
1026 #endif // !defined(USE_SYSTEM_ZLIB)
1027 } else {
1028 EXPECT_EQ(165u, uncompressed_size1);
1029 #if defined(USE_SYSTEM_ZLIB)
1030 EXPECT_EQ(181u, compressed_size1);
1031 #else // !defined(USE_SYSTEM_ZLIB)
1032 EXPECT_EQ(117u, compressed_size1);
1033 #endif // !defined(USE_SYSTEM_ZLIB)
1035 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
1036 size_t uncompressed_size2 = visitor->last_payload_len_;
1037 size_t compressed_size2 =
1038 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1040 // Expect the second frame to be more compact than the first.
1041 EXPECT_LE(frame2->size(), frame1->size());
1043 // Decompress the first frame
1044 scoped_ptr<SpdyFrame> frame3(
1045 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
1047 // Decompress the second frame
1048 visitor.reset(new TestSpdyVisitor(spdy_version_));
1049 framer.set_debug_visitor(visitor.get());
1050 scoped_ptr<SpdyFrame> frame4(
1051 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1052 size_t uncompressed_size4 =
1053 frame4->size() - framer.GetSynStreamMinimumSize();
1054 size_t compressed_size4 =
1055 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1056 if (IsSpdy2()) {
1057 EXPECT_EQ(139u, uncompressed_size4);
1058 #if defined(USE_SYSTEM_ZLIB)
1059 EXPECT_EQ(149u, compressed_size4);
1060 #else // !defined(USE_SYSTEM_ZLIB)
1061 EXPECT_EQ(101u, compressed_size4);
1062 #endif // !defined(USE_SYSTEM_ZLIB)
1063 } else {
1064 EXPECT_EQ(165u, uncompressed_size4);
1065 #if defined(USE_SYSTEM_ZLIB)
1066 EXPECT_EQ(175u, compressed_size4);
1067 #else // !defined(USE_SYSTEM_ZLIB)
1068 EXPECT_EQ(102u, compressed_size4);
1069 #endif // !defined(USE_SYSTEM_ZLIB)
1072 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1073 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1074 EXPECT_EQ(compressed_size2, compressed_size4);
1076 // Expect frames 3 & 4 to be the same.
1077 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1079 // Expect frames 3 to be the same as a uncompressed frame created
1080 // from scratch.
1081 framer.set_enable_compression(false);
1082 scoped_ptr<SpdyFrame> uncompressed_frame(
1083 framer.SerializeSynStream(syn_stream));
1084 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1087 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1088 // See crbug.com/172383
1089 SpdyHeadersIR headers(1);
1090 headers.SetHeader("server", "SpdyServer 1.0");
1091 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1092 headers.SetHeader("status", "200");
1093 headers.SetHeader("version", "HTTP/1.1");
1094 headers.SetHeader("content-type", "text/html");
1095 headers.SetHeader("content-length", "12");
1096 headers.SetHeader("x-empty-header", "");
1098 SpdyFramer framer(spdy_version_);
1099 framer.set_enable_compression(true);
1100 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1103 TEST_P(SpdyFramerTest, Basic) {
1104 const unsigned char kV2Input[] = {
1105 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1106 0x00, 0x00, 0x00, 0x14,
1107 0x00, 0x00, 0x00, 0x01,
1108 0x00, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x01,
1110 0x00, 0x02, 'h', 'h',
1111 0x00, 0x02, 'v', 'v',
1113 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1114 0x00, 0x00, 0x00, 0x18,
1115 0x00, 0x00, 0x00, 0x01,
1116 0x00, 0x00, 0x00, 0x02,
1117 0x00, 0x02, 'h', '2',
1118 0x00, 0x02, 'v', '2',
1119 0x00, 0x02, 'h', '3',
1120 0x00, 0x02, 'v', '3',
1122 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1123 0x00, 0x00, 0x00, 0x0c,
1124 0xde, 0xad, 0xbe, 0xef,
1125 0xde, 0xad, 0xbe, 0xef,
1126 0xde, 0xad, 0xbe, 0xef,
1128 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1129 0x00, 0x00, 0x00, 0x0c,
1130 0x00, 0x00, 0x00, 0x03,
1131 0x00, 0x00, 0x00, 0x00,
1132 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1135 0x00, 0x00, 0x00, 0x08,
1136 0xde, 0xad, 0xbe, 0xef,
1137 0xde, 0xad, 0xbe, 0xef,
1139 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1140 0x00, 0x00, 0x00, 0x04,
1141 0xde, 0xad, 0xbe, 0xef,
1143 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1144 0x00, 0x00, 0x00, 0x08,
1145 0x00, 0x00, 0x00, 0x01,
1146 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1148 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1149 0x00, 0x00, 0x00, 0x00,
1151 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1152 0x00, 0x00, 0x00, 0x08,
1153 0x00, 0x00, 0x00, 0x03,
1154 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1157 const unsigned char kV3Input[] = {
1158 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1159 0x00, 0x00, 0x00, 0x1a,
1160 0x00, 0x00, 0x00, 0x01,
1161 0x00, 0x00, 0x00, 0x00,
1162 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x01, 0x00, 0x00,
1164 0x00, 0x02, 'h', 'h',
1165 0x00, 0x00, 0x00, 0x02,
1166 'v', 'v',
1168 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1169 0x00, 0x00, 0x00, 0x20,
1170 0x00, 0x00, 0x00, 0x01,
1171 0x00, 0x00, 0x00, 0x02,
1172 0x00, 0x00, 0x00, 0x02,
1173 'h', '2',
1174 0x00, 0x00, 0x00, 0x02,
1175 'v', '2', 0x00, 0x00,
1176 0x00, 0x02, 'h', '3',
1177 0x00, 0x00, 0x00, 0x02,
1178 'v', '3',
1180 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1181 0x00, 0x00, 0x00, 0x0c,
1182 0xde, 0xad, 0xbe, 0xef,
1183 0xde, 0xad, 0xbe, 0xef,
1184 0xde, 0xad, 0xbe, 0xef,
1186 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1187 0x00, 0x00, 0x00, 0x0e,
1188 0x00, 0x00, 0x00, 0x03,
1189 0x00, 0x00, 0x00, 0x00,
1190 0x00, 0x00, 0x00, 0x00,
1191 0x00, 0x00,
1193 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1194 0x00, 0x00, 0x00, 0x08,
1195 0xde, 0xad, 0xbe, 0xef,
1196 0xde, 0xad, 0xbe, 0xef,
1198 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1199 0x00, 0x00, 0x00, 0x04,
1200 0xde, 0xad, 0xbe, 0xef,
1202 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1203 0x00, 0x00, 0x00, 0x08,
1204 0x00, 0x00, 0x00, 0x01,
1205 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1207 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1208 0x00, 0x00, 0x00, 0x00,
1210 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1211 0x00, 0x00, 0x00, 0x08,
1212 0x00, 0x00, 0x00, 0x03,
1213 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1216 // SYN_STREAM doesn't exist in HTTP/2, so instead we send
1217 // HEADERS frames with PRIORITY and END_HEADERS set.
1218 const unsigned char kH2Input[] = {
1219 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1220 0x24, 0x00, 0x00, 0x00,
1221 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1222 0x00, 0x82, // :method: GET
1224 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1225 0x04, 0x00, 0x00, 0x00, // Stream 1
1226 0x01, 0x8c, // :status: 200
1228 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1229 0x00, 0x00, 0x00, 0x00,
1230 0x01, 0xde, 0xad, 0xbe,
1231 0xef, 0xde, 0xad, 0xbe,
1232 0xef, 0xde, 0xad, 0xbe,
1233 0xef,
1235 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1236 0x24, 0x00, 0x00, 0x00,
1237 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1238 0x00, 0x82, // :method: GET
1240 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1241 0x00, 0x00, 0x00, 0x00,
1242 0x03, 0xde, 0xad, 0xbe,
1243 0xef, 0xde, 0xad, 0xbe,
1244 0xef,
1246 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1247 0x00, 0x00, 0x00, 0x00,
1248 0x01, 0xde, 0xad, 0xbe,
1249 0xef,
1251 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1252 0x00, 0x00, 0x00, 0x00,
1253 0x01, 0x00, 0x00, 0x00,
1254 0x08, // RST_STREAM_CANCEL
1256 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1257 0x00, 0x00, 0x00, 0x00,
1258 0x03,
1260 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1261 0x00, 0x00, 0x00, 0x00,
1262 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1263 0x08, 0x52, 0x45, 0x53, // opaque data
1264 0x45, 0x54, 0x53, 0x54,
1265 0x52, 0x45, 0x41, 0x4d,
1268 TestSpdyVisitor visitor(spdy_version_);
1269 if (IsSpdy2()) {
1270 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1271 } else if (IsSpdy3()) {
1272 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1273 } else {
1274 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1277 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1278 EXPECT_EQ(24, visitor.data_bytes_);
1279 EXPECT_EQ(0, visitor.error_count_);
1280 EXPECT_EQ(2, visitor.fin_frame_count_);
1282 if (IsHttp2()) {
1283 EXPECT_EQ(3, visitor.headers_frame_count_);
1284 EXPECT_EQ(0, visitor.syn_frame_count_);
1285 base::StringPiece reset_stream = "RESETSTREAM";
1286 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1287 } else {
1288 EXPECT_EQ(1, visitor.headers_frame_count_);
1289 EXPECT_EQ(2, visitor.syn_frame_count_);
1290 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1293 EXPECT_EQ(0, visitor.fin_flag_count_);
1294 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1295 EXPECT_EQ(4, visitor.data_frame_count_);
1296 visitor.fin_opaque_data_.clear();
1299 // Test that the FIN flag on a data frame signifies EOF.
1300 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1301 const unsigned char kV2Input[] = {
1302 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1303 0x00, 0x00, 0x00, 0x14,
1304 0x00, 0x00, 0x00, 0x01,
1305 0x00, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x01,
1307 0x00, 0x02, 'h', 'h',
1308 0x00, 0x02, 'v', 'v',
1310 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1311 0x00, 0x00, 0x00, 0x10,
1312 0x00, 0x00, 0x00, 0x01,
1313 0x00, 0x00, 0x00, 0x01,
1314 0x00, 0x02, 'a', 'a',
1315 0x00, 0x02, 'b', 'b',
1317 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1318 0x00, 0x00, 0x00, 0x0c,
1319 0xde, 0xad, 0xbe, 0xef,
1320 0xde, 0xad, 0xbe, 0xef,
1321 0xde, 0xad, 0xbe, 0xef,
1323 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1324 0x01, 0x00, 0x00, 0x04,
1325 0xde, 0xad, 0xbe, 0xef,
1327 const unsigned char kV3Input[] = {
1328 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1329 0x00, 0x00, 0x00, 0x1a,
1330 0x00, 0x00, 0x00, 0x01,
1331 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00,
1333 0x00, 0x01, 0x00, 0x00,
1334 0x00, 0x02, 'h', 'h',
1335 0x00, 0x00, 0x00, 0x02,
1336 'v', 'v',
1338 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1339 0x00, 0x00, 0x00, 0x14,
1340 0x00, 0x00, 0x00, 0x01,
1341 0x00, 0x00, 0x00, 0x01,
1342 0x00, 0x00, 0x00, 0x02,
1343 'a', 'a', 0x00, 0x00,
1344 0x00, 0x02, 'b', 'b',
1346 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1347 0x00, 0x00, 0x00, 0x0c,
1348 0xde, 0xad, 0xbe, 0xef,
1349 0xde, 0xad, 0xbe, 0xef,
1350 0xde, 0xad, 0xbe, 0xef,
1352 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1353 0x01, 0x00, 0x00, 0x04,
1354 0xde, 0xad, 0xbe, 0xef,
1357 // SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
1358 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1359 const unsigned char kH2Input[] = {
1360 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1361 0x24, 0x00, 0x00, 0x00, // Stream 1
1362 0x01, 0x00, 0x00, 0x00, // Priority 0
1363 0x00, 0x82, // :method: GET
1365 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1366 0x04, 0x00, 0x00, 0x00, // Stream 1
1367 0x01, 0x8c, // :status: 200
1369 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1370 0x00, 0x00, 0x00, 0x00,
1371 0x01, 0xde, 0xad, 0xbe,
1372 0xef, 0xde, 0xad, 0xbe,
1373 0xef, 0xde, 0xad, 0xbe,
1374 0xef,
1376 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1377 0x01, 0x00, 0x00, 0x00,
1378 0x01, 0xde, 0xad, 0xbe,
1379 0xef,
1382 TestSpdyVisitor visitor(spdy_version_);
1383 if (IsSpdy2()) {
1384 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1385 } else if (IsSpdy3()) {
1386 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1387 } else {
1388 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1391 EXPECT_EQ(0, visitor.error_count_);
1392 if (IsHttp2()) {
1393 EXPECT_EQ(0, visitor.syn_frame_count_);
1394 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1395 EXPECT_EQ(2, visitor.headers_frame_count_);
1396 } else {
1397 EXPECT_EQ(1, visitor.syn_frame_count_);
1398 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1399 EXPECT_EQ(0, visitor.headers_frame_count_);
1401 EXPECT_EQ(16, visitor.data_bytes_);
1402 EXPECT_EQ(0, visitor.fin_frame_count_);
1403 EXPECT_EQ(0, visitor.fin_flag_count_);
1404 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1405 EXPECT_EQ(2, visitor.data_frame_count_);
1408 // Test that the FIN flag on a SYN reply frame signifies EOF.
1409 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1410 const unsigned char kV2Input[] = {
1411 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1412 0x01, 0x00, 0x00, 0x00,
1413 0x14, 0x00, 0x00, 0x00,
1414 0x01, 0x00, 0x00, 0x00,
1415 0x00, 0x00, 0x00, 0x00,
1416 0x01, 0x00, 0x02, 'h',
1417 'h', 0x00, 0x02, 'v',
1418 'v',
1420 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1421 0x02, 0x01, 0x00, 0x00,
1422 0x10, 0x00, 0x00, 0x00,
1423 0x01, 0x00, 0x00, 0x00,
1424 0x01, 0x00, 0x02, 'a',
1425 'a', 0x00, 0x02, 'b',
1426 'b',
1428 const unsigned char kV3Input[] = {
1429 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1430 0x01, 0x00, 0x00, 0x00,
1431 0x1a, 0x00, 0x00, 0x00,
1432 0x01, 0x00, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x00, 0x01, 0x00,
1435 0x00, 0x00, 0x02, 'h',
1436 'h', 0x00, 0x00, 0x00,
1437 0x02, 'v', 'v',
1439 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1440 0x02, 0x01, 0x00, 0x00,
1441 0x14, 0x00, 0x00, 0x00,
1442 0x01, 0x00, 0x00, 0x00,
1443 0x01, 0x00, 0x00, 0x00,
1444 0x02, 'a', 'a', 0x00,
1445 0x00, 0x00, 0x02, 'b',
1446 'b',
1449 // SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
1450 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1451 const unsigned char kH2Input[] = {
1452 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1453 0x24, 0x00, 0x00, 0x00,
1454 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1455 0x00, 0x82, // :method: GET
1457 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1458 0x05, 0x00, 0x00, 0x00,
1459 0x01, 0x8c, // Stream 1, :status: 200
1462 TestSpdyVisitor visitor(spdy_version_);
1463 if (IsSpdy2()) {
1464 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1465 } else if (IsSpdy3()) {
1466 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1467 } else {
1468 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1471 EXPECT_EQ(0, visitor.error_count_);
1472 if (IsHttp2()) {
1473 EXPECT_EQ(0, visitor.syn_frame_count_);
1474 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1475 EXPECT_EQ(2, visitor.headers_frame_count_);
1476 } else {
1477 EXPECT_EQ(1, visitor.syn_frame_count_);
1478 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1479 EXPECT_EQ(0, visitor.headers_frame_count_);
1481 EXPECT_EQ(0, visitor.data_bytes_);
1482 EXPECT_EQ(0, visitor.fin_frame_count_);
1483 EXPECT_EQ(1, visitor.fin_flag_count_);
1484 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1485 EXPECT_EQ(0, visitor.data_frame_count_);
1488 TEST_P(SpdyFramerTest, HeaderCompression) {
1489 if (spdy_version_ > SPDY3) {
1490 // Deflate compression doesn't apply to HPACK.
1491 return;
1493 SpdyFramer send_framer(spdy_version_);
1494 SpdyFramer recv_framer(spdy_version_);
1496 send_framer.set_enable_compression(true);
1497 recv_framer.set_enable_compression(true);
1499 const char kHeader1[] = "header1";
1500 const char kHeader2[] = "header2";
1501 const char kHeader3[] = "header3";
1502 const char kValue1[] = "value1";
1503 const char kValue2[] = "value2";
1504 const char kValue3[] = "value3";
1506 // SYN_STREAM #1
1507 SpdyHeaderBlock block;
1508 block[kHeader1] = kValue1;
1509 block[kHeader2] = kValue2;
1510 SpdySynStreamIR syn_ir_1(1);
1511 syn_ir_1.set_name_value_block(block);
1512 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1513 EXPECT_TRUE(syn_frame_1.get() != NULL);
1515 // SYN_STREAM #2
1516 block[kHeader3] = kValue3;
1517 SpdySynStreamIR syn_stream(3);
1518 syn_stream.set_name_value_block(block);
1519 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1520 EXPECT_TRUE(syn_frame_2.get() != NULL);
1522 // Now start decompressing
1523 scoped_ptr<SpdyFrame> decompressed;
1524 scoped_ptr<SpdyFrame> uncompressed;
1525 base::StringPiece serialized_headers;
1526 SpdyHeaderBlock decompressed_headers;
1528 // Decompress SYN_STREAM #1
1529 decompressed.reset(
1530 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1531 EXPECT_TRUE(decompressed.get() != NULL);
1532 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1533 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1534 serialized_headers.size(),
1535 &decompressed_headers));
1536 EXPECT_EQ(2u, decompressed_headers.size());
1537 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1538 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1540 // Decompress SYN_STREAM #2
1541 decompressed.reset(
1542 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1543 EXPECT_TRUE(decompressed.get() != NULL);
1544 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1545 decompressed_headers.clear();
1546 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1547 serialized_headers.size(),
1548 &decompressed_headers));
1549 EXPECT_EQ(3u, decompressed_headers.size());
1550 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1551 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1552 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1555 // Verify we can decompress the stream even if handed over to the
1556 // framer 1 byte at a time.
1557 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1558 SpdyFramer send_framer(spdy_version_);
1560 send_framer.set_enable_compression(true);
1562 const char kHeader1[] = "header1";
1563 const char kHeader2[] = "header2";
1564 const char kValue1[] = "value1";
1565 const char kValue2[] = "value2";
1567 SpdyHeadersIR headers(1);
1568 headers.SetHeader(kHeader1, kValue1);
1569 headers.SetHeader(kHeader2, kValue2);
1570 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1571 EXPECT_TRUE(headers_frame.get() != NULL);
1573 const char bytes[] = "this is a test test test test test!";
1574 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1575 data_ir.set_fin(true);
1576 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1577 EXPECT_TRUE(send_frame.get() != NULL);
1579 // Run the inputs through the framer.
1580 TestSpdyVisitor visitor(spdy_version_);
1581 visitor.use_compression_ = true;
1582 const unsigned char* data;
1583 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1584 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1585 visitor.SimulateInFramer(data + idx, 1);
1586 ASSERT_EQ(0, visitor.error_count_);
1588 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1589 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1590 visitor.SimulateInFramer(data + idx, 1);
1591 ASSERT_EQ(0, visitor.error_count_);
1594 EXPECT_EQ(0, visitor.error_count_);
1595 EXPECT_EQ(0, visitor.syn_frame_count_);
1596 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1597 EXPECT_EQ(1, visitor.headers_frame_count_);
1598 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1599 EXPECT_EQ(0, visitor.fin_frame_count_);
1600 EXPECT_EQ(0, visitor.fin_flag_count_);
1601 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1602 EXPECT_EQ(1, visitor.data_frame_count_);
1605 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1606 SpdyFramer framer(spdy_version_);
1607 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1608 SpdyWindowUpdateIR(1, 0x12345678)));
1610 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1611 const unsigned char kV3FrameData[] = { // Also applies for V2.
1612 0x80, spdy_version_ch_, 0x00, 0x09,
1613 0x00, 0x00, 0x00, 0x08,
1614 0x00, 0x00, 0x00, 0x01,
1615 0x12, 0x34, 0x56, 0x78
1617 const unsigned char kH2FrameData[] = {
1618 0x00, 0x00, 0x04, 0x08,
1619 0x00, 0x00, 0x00, 0x00,
1620 0x01, 0x12, 0x34, 0x56,
1621 0x78
1624 if (IsHttp2()) {
1625 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1626 } else {
1627 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1631 TEST_P(SpdyFramerTest, CreateDataFrame) {
1632 SpdyFramer framer(spdy_version_);
1635 const char kDescription[] = "'hello' data frame, no FIN";
1636 const unsigned char kV3FrameData[] = { // Also applies for V2.
1637 0x00, 0x00, 0x00, 0x01,
1638 0x00, 0x00, 0x00, 0x05,
1639 'h', 'e', 'l', 'l',
1642 const unsigned char kH2FrameData[] = {0x00,
1643 0x00,
1644 0x05,
1645 0x00,
1646 0x00,
1647 0x00,
1648 0x00,
1649 0x00,
1650 0x01,
1651 'h',
1652 'e',
1653 'l',
1654 'l',
1655 'o'};
1656 const char bytes[] = "hello";
1658 SpdyDataIR data_ir(1, bytes);
1659 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1660 if (IsHttp2()) {
1661 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1662 } else {
1663 CompareFrame(
1664 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1667 SpdyDataIR data_header_ir(1);
1668 data_header_ir.SetDataShallow(bytes);
1669 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1670 data_header_ir));
1671 CompareCharArraysWithHexError(
1672 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1673 framer.GetDataFrameMinimumSize(),
1674 IsHttp2() ? kH2FrameData : kV3FrameData,
1675 framer.GetDataFrameMinimumSize());
1679 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1680 const unsigned char kV3FrameData[] = { // Also applies for V2.
1681 0x00, 0x00, 0x00, 0x01,
1682 0x00, 0x00, 0x00, 0x05,
1683 'h', 'e', 'l', 'l',
1687 const unsigned char kH2FrameData[] = {
1688 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1689 0x08, 0x00, 0x00, 0x00,
1690 0x01, 0xf7, // Pad length field.
1691 'h', 'e', 'l', 'l', // Data
1692 'o',
1693 // Padding of 247 0x00(s).
1694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1716 const char bytes[] = "hello";
1718 SpdyDataIR data_ir(1, bytes);
1719 // 247 zeros and the pad length field make the overall padding to be 248
1720 // bytes.
1721 data_ir.set_padding_len(248);
1722 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1723 if (IsHttp2()) {
1724 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1725 } else {
1726 CompareFrame(
1727 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1730 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1731 CompareCharArraysWithHexError(
1732 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1733 framer.GetDataFrameMinimumSize(),
1734 IsHttp2() ? kH2FrameData : kV3FrameData,
1735 framer.GetDataFrameMinimumSize());
1739 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1740 const unsigned char kV3FrameData[] = { // Also applies for V2.
1741 0x00, 0x00, 0x00, 0x01,
1742 0x00, 0x00, 0x00, 0x05,
1743 'h', 'e', 'l', 'l',
1747 const unsigned char kH2FrameData[] = {
1748 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1749 0x08, 0x00, 0x00, 0x00,
1750 0x01, 0x07, // Pad length field.
1751 'h', 'e', 'l', 'l', // Data
1752 'o',
1753 0x00, 0x00, 0x00, 0x00, // Padding
1754 0x00, 0x00, 0x00
1756 const char bytes[] = "hello";
1758 SpdyDataIR data_ir(1, bytes);
1759 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1760 data_ir.set_padding_len(8);
1761 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1762 if (IsHttp2()) {
1763 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1764 } else {
1765 CompareFrame(
1766 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1771 const char kDescription[] =
1772 "'hello' data frame with 1 byte padding, no FIN";
1773 const unsigned char kV3FrameData[] = { // Also applies for V2.
1774 0x00, 0x00, 0x00, 0x01,
1775 0x00, 0x00, 0x00, 0x05,
1776 'h', 'e', 'l', 'l',
1780 const unsigned char kH2FrameData[] = {
1781 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1782 0x08, 0x00, 0x00, 0x00,
1783 0x01, 0x00, // Pad length field.
1784 'h', 'e', 'l', 'l', // Data
1785 'o',
1787 const char bytes[] = "hello";
1789 SpdyDataIR data_ir(1, bytes);
1790 // The pad length field itself is used for the 1-byte padding and no padding
1791 // payload is needed.
1792 data_ir.set_padding_len(1);
1793 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1794 if (IsHttp2()) {
1795 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1796 } else {
1797 CompareFrame(
1798 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1801 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1802 CompareCharArraysWithHexError(
1803 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1804 framer.GetDataFrameMinimumSize(),
1805 IsHttp2() ? kH2FrameData : kV3FrameData,
1806 framer.GetDataFrameMinimumSize());
1810 const char kDescription[] = "Data frame with negative data byte, no FIN";
1811 const unsigned char kV3FrameData[] = { // Also applies for V2.
1812 0x00, 0x00, 0x00, 0x01,
1813 0x00, 0x00, 0x00, 0x01,
1814 0xff
1816 const unsigned char kH2FrameData[] = {
1817 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff};
1818 SpdyDataIR data_ir(1, "\xff");
1819 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1820 if (IsHttp2()) {
1821 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1822 } else {
1823 CompareFrame(
1824 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1829 const char kDescription[] = "'hello' data frame, with FIN";
1830 const unsigned char kV3FrameData[] = { // Also applies for V2.
1831 0x00, 0x00, 0x00, 0x01,
1832 0x01, 0x00, 0x00, 0x05,
1833 'h', 'e', 'l', 'l',
1836 const unsigned char kH2FrameData[] = {
1837 0x00, 0x00, 0x05, 0x00,
1838 0x01, 0x00, 0x00, 0x00,
1839 0x01, 'h', 'e', 'l',
1840 'l', 'o'
1842 SpdyDataIR data_ir(1, "hello");
1843 data_ir.set_fin(true);
1844 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1845 if (IsHttp2()) {
1846 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1847 } else {
1848 CompareFrame(
1849 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1854 const char kDescription[] = "Empty data frame";
1855 const unsigned char kV3FrameData[] = { // Also applies for V2.
1856 0x00, 0x00, 0x00, 0x01,
1857 0x00, 0x00, 0x00, 0x00,
1859 const unsigned char kH2FrameData[] = {
1860 0x00, 0x00, 0x00, 0x00,
1861 0x00, 0x00, 0x00, 0x00,
1862 0x01,
1864 SpdyDataIR data_ir(1, "");
1865 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1866 if (IsHttp2()) {
1867 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1868 } else {
1869 CompareFrame(
1870 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1873 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1874 CompareCharArraysWithHexError(
1875 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1876 framer.GetDataFrameMinimumSize(),
1877 IsHttp2() ? kH2FrameData : kV3FrameData,
1878 framer.GetDataFrameMinimumSize());
1882 const char kDescription[] = "Data frame with max stream ID";
1883 const unsigned char kV3FrameData[] = { // Also applies for V2.
1884 0x7f, 0xff, 0xff, 0xff,
1885 0x01, 0x00, 0x00, 0x05,
1886 'h', 'e', 'l', 'l',
1889 const unsigned char kH2FrameData[] = {
1890 0x00, 0x00, 0x05, 0x00,
1891 0x01, 0x7f, 0xff, 0xff,
1892 0xff, 'h', 'e', 'l',
1893 'l', 'o'
1895 SpdyDataIR data_ir(0x7fffffff, "hello");
1896 data_ir.set_fin(true);
1897 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1898 if (IsHttp2()) {
1899 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1900 } else {
1901 CompareFrame(
1902 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1906 if (!IsHttp2()) {
1907 // This test does not apply to HTTP/2 because the max frame size is smaller
1908 // than 4MB.
1909 const char kDescription[] = "Large data frame";
1910 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1911 const string kData(kDataSize, 'A');
1912 const unsigned char kFrameHeader[] = {
1913 0x00, 0x00, 0x00, 0x01,
1914 0x01, 0x40, 0x00, 0x00,
1917 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1918 scoped_ptr<unsigned char[]> expected_frame_data(
1919 new unsigned char[kFrameSize]);
1920 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1921 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1923 SpdyDataIR data_ir(1, kData);
1924 data_ir.set_fin(true);
1925 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1926 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1930 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1931 if (!IsSpdy2() && !IsSpdy3()) {
1932 // SYN_STREAM unsupported in SPDY>3
1933 return;
1935 SpdyFramer framer(spdy_version_);
1936 framer.set_enable_compression(false);
1939 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1941 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1942 const unsigned char kV2FrameData[] = {
1943 0x80, spdy_version_ch_, 0x00, 0x01,
1944 0x00, 0x00, 0x00, 0x20,
1945 0x00, 0x00, 0x00, 0x01,
1946 0x00, 0x00, 0x00, 0x00,
1947 kPri, 0x00, 0x00, 0x02,
1948 0x00, 0x03, 'b', 'a',
1949 'r', 0x00, 0x03, 'f',
1950 'o', 'o', 0x00, 0x03,
1951 'f', 'o', 'o', 0x00,
1952 0x03, 'b', 'a', 'r'
1954 const unsigned char kV3FrameData[] = {
1955 0x80, spdy_version_ch_, 0x00, 0x01,
1956 0x00, 0x00, 0x00, 0x2a,
1957 0x00, 0x00, 0x00, 0x01,
1958 0x00, 0x00, 0x00, 0x00,
1959 kPri, 0x00, 0x00, 0x00,
1960 0x00, 0x02, 0x00, 0x00,
1961 0x00, 0x03, 'b', 'a',
1962 'r', 0x00, 0x00, 0x00,
1963 0x03, 'f', 'o', 'o',
1964 0x00, 0x00, 0x00, 0x03,
1965 'f', 'o', 'o', 0x00,
1966 0x00, 0x00, 0x03, 'b',
1967 'a', 'r'
1969 SpdySynStreamIR syn_stream(1);
1970 syn_stream.set_priority(framer.GetLowestPriority());
1971 syn_stream.SetHeader("bar", "foo");
1972 syn_stream.SetHeader("foo", "bar");
1973 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1974 if (IsSpdy2()) {
1975 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1976 } else if (IsSpdy3()) {
1977 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1978 } else {
1979 LOG(FATAL) << "Unsupported version in test.";
1984 const char kDescription[] =
1985 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1986 "max stream ID";
1988 const unsigned char kV2FrameData[] = {
1989 0x80, spdy_version_ch_, 0x00, 0x01,
1990 0x01, 0x00, 0x00, 0x1D,
1991 0x7f, 0xff, 0xff, 0xff,
1992 0x7f, 0xff, 0xff, 0xff,
1993 0x00, 0x00, 0x00, 0x02,
1994 0x00, 0x00, 0x00, 0x03,
1995 'f', 'o', 'o', 0x00,
1996 0x03, 'f', 'o', 'o',
1997 0x00, 0x03, 'b', 'a',
2000 const unsigned char kV3FrameData[] = {
2001 0x80, spdy_version_ch_, 0x00, 0x01,
2002 0x01, 0x00, 0x00, 0x27,
2003 0x7f, 0xff, 0xff, 0xff,
2004 0x7f, 0xff, 0xff, 0xff,
2005 0x00, 0x00, 0x00, 0x00,
2006 0x00, 0x02, 0x00, 0x00,
2007 0x00, 0x00, 0x00, 0x00,
2008 0x00, 0x03, 'f', 'o',
2009 'o', 0x00, 0x00, 0x00,
2010 0x03, 'f', 'o', 'o',
2011 0x00, 0x00, 0x00, 0x03,
2012 'b', 'a', 'r'
2014 SpdySynStreamIR syn_stream(0x7fffffff);
2015 syn_stream.set_associated_to_stream_id(0x7fffffff);
2016 syn_stream.set_priority(framer.GetHighestPriority());
2017 syn_stream.set_fin(true);
2018 syn_stream.SetHeader("", "foo");
2019 syn_stream.SetHeader("foo", "bar");
2020 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2021 if (IsSpdy2()) {
2022 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2023 } else if (IsSpdy3()) {
2024 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2025 } else {
2026 LOG(FATAL) << "Unsupported version in test.";
2031 const char kDescription[] =
2032 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
2033 "max stream ID";
2035 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
2036 const unsigned char kV2FrameData[] = {
2037 0x80, spdy_version_ch_, 0x00, 0x01,
2038 0x01, 0x00, 0x00, 0x1D,
2039 0x7f, 0xff, 0xff, 0xff,
2040 0x7f, 0xff, 0xff, 0xff,
2041 kPri, 0x00, 0x00, 0x02,
2042 0x00, 0x03, 'b', 'a',
2043 'r', 0x00, 0x03, 'f',
2044 'o', 'o', 0x00, 0x03,
2045 'f', 'o', 'o', 0x00,
2046 0x00
2048 const unsigned char kV3FrameData[] = {
2049 0x80, spdy_version_ch_, 0x00, 0x01,
2050 0x01, 0x00, 0x00, 0x27,
2051 0x7f, 0xff, 0xff, 0xff,
2052 0x7f, 0xff, 0xff, 0xff,
2053 kPri, 0x00, 0x00, 0x00,
2054 0x00, 0x02, 0x00, 0x00,
2055 0x00, 0x03, 'b', 'a',
2056 'r', 0x00, 0x00, 0x00,
2057 0x03, 'f', 'o', 'o',
2058 0x00, 0x00, 0x00, 0x03,
2059 'f', 'o', 'o', 0x00,
2060 0x00, 0x00, 0x00
2062 SpdySynStreamIR syn_stream(0x7fffffff);
2063 syn_stream.set_associated_to_stream_id(0x7fffffff);
2064 syn_stream.set_priority(1);
2065 syn_stream.set_fin(true);
2066 syn_stream.SetHeader("bar", "foo");
2067 syn_stream.SetHeader("foo", "");
2068 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2069 if (IsSpdy2()) {
2070 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2071 } else if (IsSpdy3()) {
2072 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2073 } else {
2074 LOG(FATAL) << "Unsupported version in test.";
2079 // TODO(phajdan.jr): Clean up after we no longer need
2080 // to workaround http://crbug.com/139744.
2081 #if !defined(USE_SYSTEM_ZLIB)
2082 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2083 if (!IsSpdy2() && !IsSpdy3()) {
2084 // SYN_STREAM not supported for SPDY>3
2085 return;
2087 SpdyFramer framer(spdy_version_);
2088 framer.set_enable_compression(true);
2091 const char kDescription[] =
2092 "SYN_STREAM frame, low pri, no FIN";
2093 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2095 const unsigned char kV2FrameData[] = {
2096 0x80, spdy_version_ch_, 0x00, 0x01,
2097 0x00, 0x00, 0x00, 0x36,
2098 0x00, 0x00, 0x00, 0x01,
2099 0x00, 0x00, 0x00, 0x00,
2100 0x80, 0x00, 0x38, 0xea,
2101 0xdf, 0xa2, 0x51, 0xb2,
2102 0x62, 0x60, 0x62, 0x60,
2103 0x4e, 0x4a, 0x2c, 0x62,
2104 0x60, 0x06, 0x08, 0xa0,
2105 0xb4, 0xfc, 0x7c, 0x80,
2106 0x00, 0x62, 0x60, 0x4e,
2107 0xcb, 0xcf, 0x67, 0x60,
2108 0x06, 0x08, 0xa0, 0xa4,
2109 0xc4, 0x22, 0x80, 0x00,
2110 0x02, 0x00, 0x00, 0x00,
2111 0xff, 0xff,
2113 const unsigned char kV3FrameData[] = {
2114 0x80, spdy_version_ch_, 0x00, 0x01,
2115 0x00, 0x00, 0x00, 0x37,
2116 0x00, 0x00, 0x00, 0x01,
2117 0x00, 0x00, 0x00, 0x00,
2118 0x80, 0x00, 0x38, 0xEA,
2119 0xE3, 0xC6, 0xA7, 0xC2,
2120 0x02, 0xE5, 0x0E, 0x50,
2121 0xC2, 0x4B, 0x4A, 0x04,
2122 0xE5, 0x0B, 0x66, 0x80,
2123 0x00, 0x4A, 0xCB, 0xCF,
2124 0x07, 0x08, 0x20, 0x10,
2125 0x95, 0x96, 0x9F, 0x0F,
2126 0xA2, 0x00, 0x02, 0x28,
2127 0x29, 0xB1, 0x08, 0x20,
2128 0x80, 0x00, 0x00, 0x00,
2129 0x00, 0xFF, 0xFF,
2131 const unsigned char kV2SIMDFrameData[] = {
2132 0x80, spdy_version_ch_, 0x00, 0x01,
2133 0x00, 0x00, 0x00, 0x33,
2134 0x00, 0x00, 0x00, 0x01,
2135 0x00, 0x00, 0x00, 0x00,
2136 0x80, 0x00, 0x38, 0xea,
2137 0xdf, 0xa2, 0x51, 0xb2,
2138 0x62, 0x60, 0x62, 0x60,
2139 0x4e, 0x4a, 0x2c, 0x62,
2140 0x60, 0x06, 0x08, 0xa0,
2141 0xb4, 0xfc, 0x7c, 0x80,
2142 0x00, 0x62, 0x60, 0x06,
2143 0x13, 0x00, 0x01, 0x94,
2144 0x94, 0x58, 0x04, 0x10,
2145 0x40, 0x00, 0x00, 0x00,
2146 0x00, 0xff, 0xff,
2148 const unsigned char kV3SIMDFrameData[] = {
2149 0x80, spdy_version_ch_, 0x00, 0x01,
2150 0x00, 0x00, 0x00, 0x32,
2151 0x00, 0x00, 0x00, 0x01,
2152 0x00, 0x00, 0x00, 0x00,
2153 0x80, 0x00, 0x38, 0xea,
2154 0xe3, 0xc6, 0xa7, 0xc2,
2155 0x02, 0xe5, 0x0e, 0x50,
2156 0xc2, 0x4b, 0x4a, 0x04,
2157 0xe5, 0x0b, 0x66, 0x80,
2158 0x00, 0x4a, 0xcb, 0xcf,
2159 0x07, 0x08, 0x20, 0x24,
2160 0x0a, 0x20, 0x80, 0x92,
2161 0x12, 0x8b, 0x00, 0x02,
2162 0x08, 0x00, 0x00, 0x00,
2163 0xff, 0xff,
2166 SpdySynStreamIR syn_stream(1);
2167 syn_stream.set_priority(priority);
2168 syn_stream.SetHeader("bar", "foo");
2169 syn_stream.SetHeader("foo", "bar");
2170 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2171 const unsigned char* frame_data =
2172 reinterpret_cast<const unsigned char*>(frame->data());
2173 if (IsSpdy2()) {
2174 // Try comparing with SIMD version, if that fails, do a failing check
2175 // with pretty printing against non-SIMD version
2176 if (memcmp(frame_data,
2177 kV2SIMDFrameData,
2178 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2179 CompareCharArraysWithHexError(kDescription,
2180 frame_data,
2181 frame->size(),
2182 kV2FrameData,
2183 arraysize(kV2FrameData));
2185 } else if (IsSpdy3()) {
2186 if (memcmp(frame_data,
2187 kV3SIMDFrameData,
2188 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2189 CompareCharArraysWithHexError(kDescription,
2190 frame_data,
2191 frame->size(),
2192 kV3FrameData,
2193 arraysize(kV3FrameData));
2195 } else {
2196 LOG(FATAL) << "Unsupported version in test.";
2200 #endif // !defined(USE_SYSTEM_ZLIB)
2202 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2203 if (spdy_version_ > SPDY3) {
2204 // SYN_REPLY unsupported in SPDY>3
2205 return;
2207 SpdyFramer framer(spdy_version_);
2208 framer.set_enable_compression(false);
2211 const char kDescription[] = "SYN_REPLY frame, no FIN";
2213 const unsigned char kV2FrameData[] = {
2214 0x80, spdy_version_ch_, 0x00, 0x02,
2215 0x00, 0x00, 0x00, 0x1C,
2216 0x00, 0x00, 0x00, 0x01,
2217 0x00, 0x00, 0x00, 0x02,
2218 0x00, 0x03, 'b', 'a',
2219 'r', 0x00, 0x03, 'f',
2220 'o', 'o', 0x00, 0x03,
2221 'f', 'o', 'o', 0x00,
2222 0x03, 'b', 'a', 'r'
2224 const unsigned char kV3FrameData[] = {
2225 0x80, spdy_version_ch_, 0x00, 0x02,
2226 0x00, 0x00, 0x00, 0x24,
2227 0x00, 0x00, 0x00, 0x01,
2228 0x00, 0x00, 0x00, 0x02,
2229 0x00, 0x00, 0x00, 0x03,
2230 'b', 'a', 'r', 0x00,
2231 0x00, 0x00, 0x03, 'f',
2232 'o', 'o', 0x00, 0x00,
2233 0x00, 0x03, 'f', 'o',
2234 'o', 0x00, 0x00, 0x00,
2235 0x03, 'b', 'a', 'r'
2237 SpdySynReplyIR syn_reply(1);
2238 syn_reply.SetHeader("bar", "foo");
2239 syn_reply.SetHeader("foo", "bar");
2240 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2241 if (IsSpdy2()) {
2242 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2243 } else if (IsSpdy3()) {
2244 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2245 } else {
2246 LOG(FATAL) << "Unsupported version in test.";
2251 const char kDescription[] =
2252 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2254 const unsigned char kV2FrameData[] = {
2255 0x80, spdy_version_ch_, 0x00, 0x02,
2256 0x01, 0x00, 0x00, 0x19,
2257 0x7f, 0xff, 0xff, 0xff,
2258 0x00, 0x00, 0x00, 0x02,
2259 0x00, 0x00, 0x00, 0x03,
2260 'f', 'o', 'o', 0x00,
2261 0x03, 'f', 'o', 'o',
2262 0x00, 0x03, 'b', 'a',
2265 const unsigned char kV3FrameData[] = {
2266 0x80, spdy_version_ch_, 0x00, 0x02,
2267 0x01, 0x00, 0x00, 0x21,
2268 0x7f, 0xff, 0xff, 0xff,
2269 0x00, 0x00, 0x00, 0x02,
2270 0x00, 0x00, 0x00, 0x00,
2271 0x00, 0x00, 0x00, 0x03,
2272 'f', 'o', 'o', 0x00,
2273 0x00, 0x00, 0x03, 'f',
2274 'o', 'o', 0x00, 0x00,
2275 0x00, 0x03, 'b', 'a',
2278 SpdySynReplyIR syn_reply(0x7fffffff);
2279 syn_reply.set_fin(true);
2280 syn_reply.SetHeader("", "foo");
2281 syn_reply.SetHeader("foo", "bar");
2282 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2283 if (IsSpdy2()) {
2284 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2285 } else if (IsSpdy3()) {
2286 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2287 } else {
2288 LOG(FATAL) << "Unsupported version in test.";
2293 const char kDescription[] =
2294 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2296 const unsigned char kV2FrameData[] = {
2297 0x80, spdy_version_ch_, 0x00, 0x02,
2298 0x01, 0x00, 0x00, 0x19,
2299 0x7f, 0xff, 0xff, 0xff,
2300 0x00, 0x00, 0x00, 0x02,
2301 0x00, 0x03, 'b', 'a',
2302 'r', 0x00, 0x03, 'f',
2303 'o', 'o', 0x00, 0x03,
2304 'f', 'o', 'o', 0x00,
2305 0x00
2307 const unsigned char kV3FrameData[] = {
2308 0x80, spdy_version_ch_, 0x00, 0x02,
2309 0x01, 0x00, 0x00, 0x21,
2310 0x7f, 0xff, 0xff, 0xff,
2311 0x00, 0x00, 0x00, 0x02,
2312 0x00, 0x00, 0x00, 0x03,
2313 'b', 'a', 'r', 0x00,
2314 0x00, 0x00, 0x03, 'f',
2315 'o', 'o', 0x00, 0x00,
2316 0x00, 0x03, 'f', 'o',
2317 'o', 0x00, 0x00, 0x00,
2318 0x00
2320 SpdySynReplyIR syn_reply(0x7fffffff);
2321 syn_reply.set_fin(true);
2322 syn_reply.SetHeader("bar", "foo");
2323 syn_reply.SetHeader("foo", "");
2324 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2325 if (IsSpdy2()) {
2326 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2327 } else if (IsSpdy3()) {
2328 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2329 } else {
2330 LOG(FATAL) << "Unsupported version in test.";
2335 // TODO(phajdan.jr): Clean up after we no longer need
2336 // to workaround http://crbug.com/139744.
2337 #if !defined(USE_SYSTEM_ZLIB)
2338 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2339 if (spdy_version_ > SPDY3) {
2340 // SYN_REPLY unsupported in SPDY>3
2341 return;
2343 SpdyFramer framer(spdy_version_);
2344 framer.set_enable_compression(true);
2347 const char kDescription[] = "SYN_REPLY frame, no FIN";
2349 const unsigned char kV2FrameData[] = {
2350 0x80, spdy_version_ch_, 0x00, 0x02,
2351 0x00, 0x00, 0x00, 0x32,
2352 0x00, 0x00, 0x00, 0x01,
2353 0x00, 0x00, 0x38, 0xea,
2354 0xdf, 0xa2, 0x51, 0xb2,
2355 0x62, 0x60, 0x62, 0x60,
2356 0x4e, 0x4a, 0x2c, 0x62,
2357 0x60, 0x06, 0x08, 0xa0,
2358 0xb4, 0xfc, 0x7c, 0x80,
2359 0x00, 0x62, 0x60, 0x4e,
2360 0xcb, 0xcf, 0x67, 0x60,
2361 0x06, 0x08, 0xa0, 0xa4,
2362 0xc4, 0x22, 0x80, 0x00,
2363 0x02, 0x00, 0x00, 0x00,
2364 0xff, 0xff,
2366 const unsigned char kV3FrameData[] = {
2367 0x80, spdy_version_ch_, 0x00, 0x02,
2368 0x00, 0x00, 0x00, 0x31,
2369 0x00, 0x00, 0x00, 0x01,
2370 0x38, 0xea, 0xe3, 0xc6,
2371 0xa7, 0xc2, 0x02, 0xe5,
2372 0x0e, 0x50, 0xc2, 0x4b,
2373 0x4a, 0x04, 0xe5, 0x0b,
2374 0x66, 0x80, 0x00, 0x4a,
2375 0xcb, 0xcf, 0x07, 0x08,
2376 0x20, 0x10, 0x95, 0x96,
2377 0x9f, 0x0f, 0xa2, 0x00,
2378 0x02, 0x28, 0x29, 0xb1,
2379 0x08, 0x20, 0x80, 0x00,
2380 0x00, 0x00, 0x00, 0xff,
2381 0xff,
2383 const unsigned char kV2SIMDFrameData[] = {
2384 0x80, spdy_version_ch_, 0x00, 0x02,
2385 0x00, 0x00, 0x00, 0x2f,
2386 0x00, 0x00, 0x00, 0x01,
2387 0x00, 0x00, 0x38, 0xea,
2388 0xdf, 0xa2, 0x51, 0xb2,
2389 0x62, 0x60, 0x62, 0x60,
2390 0x4e, 0x4a, 0x2c, 0x62,
2391 0x60, 0x06, 0x08, 0xa0,
2392 0xb4, 0xfc, 0x7c, 0x80,
2393 0x00, 0x62, 0x60, 0x06,
2394 0x13, 0x00, 0x01, 0x94,
2395 0x94, 0x58, 0x04, 0x10,
2396 0x40, 0x00, 0x00, 0x00,
2397 0x00, 0xff, 0xff,
2399 const unsigned char kV3SIMDFrameData[] = {
2400 0x80, spdy_version_ch_, 0x00, 0x02,
2401 0x00, 0x00, 0x00, 0x2c,
2402 0x00, 0x00, 0x00, 0x01,
2403 0x38, 0xea, 0xe3, 0xc6,
2404 0xa7, 0xc2, 0x02, 0xe5,
2405 0x0e, 0x50, 0xc2, 0x4b,
2406 0x4a, 0x04, 0xe5, 0x0b,
2407 0x66, 0x80, 0x00, 0x4a,
2408 0xcb, 0xcf, 0x07, 0x08,
2409 0x20, 0x24, 0x0a, 0x20,
2410 0x80, 0x92, 0x12, 0x8b,
2411 0x00, 0x02, 0x08, 0x00,
2412 0x00, 0x00, 0xff, 0xff,
2415 SpdySynReplyIR syn_reply(1);
2416 syn_reply.SetHeader("bar", "foo");
2417 syn_reply.SetHeader("foo", "bar");
2418 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2419 const unsigned char* frame_data =
2420 reinterpret_cast<const unsigned char*>(frame->data());
2421 if (IsSpdy2()) {
2422 // Try comparing with SIMD version, if that fails, do a failing check
2423 // with pretty printing against non-SIMD version
2424 if (memcmp(frame_data,
2425 kV2SIMDFrameData,
2426 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2427 CompareCharArraysWithHexError(kDescription,
2428 frame_data,
2429 frame->size(),
2430 kV2FrameData,
2431 arraysize(kV2FrameData));
2433 } else if (IsSpdy3()) {
2434 if (memcmp(frame_data,
2435 kV3SIMDFrameData,
2436 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2437 CompareCharArraysWithHexError(kDescription,
2438 frame_data,
2439 frame->size(),
2440 kV3FrameData,
2441 arraysize(kV3FrameData));
2443 } else {
2444 LOG(FATAL) << "Unsupported version in test.";
2448 #endif // !defined(USE_SYSTEM_ZLIB)
2450 TEST_P(SpdyFramerTest, CreateRstStream) {
2451 SpdyFramer framer(spdy_version_);
2454 const char kDescription[] = "RST_STREAM frame";
2455 const unsigned char kV3FrameData[] = { // Also applies for V2.
2456 0x80, spdy_version_ch_, 0x00, 0x03,
2457 0x00, 0x00, 0x00, 0x08,
2458 0x00, 0x00, 0x00, 0x01,
2459 0x00, 0x00, 0x00, 0x01,
2461 const unsigned char kH2FrameData[] = {
2462 0x00, 0x00, 0x07, 0x03,
2463 0x00, 0x00, 0x00, 0x00,
2464 0x01, 0x00, 0x00, 0x00,
2465 0x01, 0x52, 0x53, 0x54
2467 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2468 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2469 if (IsHttp2()) {
2470 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2471 } else {
2472 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2477 const char kDescription[] = "RST_STREAM frame with max stream ID";
2478 const unsigned char kV3FrameData[] = { // Also applies for V2.
2479 0x80, spdy_version_ch_, 0x00, 0x03,
2480 0x00, 0x00, 0x00, 0x08,
2481 0x7f, 0xff, 0xff, 0xff,
2482 0x00, 0x00, 0x00, 0x01,
2484 const unsigned char kH2FrameData[] = {
2485 0x00, 0x00, 0x04, 0x03,
2486 0x00, 0x7f, 0xff, 0xff,
2487 0xff, 0x00, 0x00, 0x00,
2488 0x01,
2490 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2491 RST_STREAM_PROTOCOL_ERROR,
2492 "");
2493 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2494 if (IsHttp2()) {
2495 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2496 } else {
2497 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2502 const char kDescription[] = "RST_STREAM frame with max status code";
2503 const unsigned char kV3FrameData[] = { // Also applies for V2.
2504 0x80, spdy_version_ch_, 0x00, 0x03,
2505 0x00, 0x00, 0x00, 0x08,
2506 0x7f, 0xff, 0xff, 0xff,
2507 0x00, 0x00, 0x00, 0x06,
2509 const unsigned char kH2FrameData[] = {
2510 0x00, 0x00, 0x04, 0x03,
2511 0x00, 0x7f, 0xff, 0xff,
2512 0xff, 0x00, 0x00, 0x00,
2513 0x02,
2515 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2516 RST_STREAM_INTERNAL_ERROR,
2517 "");
2518 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2519 if (IsHttp2()) {
2520 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2521 } else {
2522 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2527 TEST_P(SpdyFramerTest, CreateSettings) {
2528 SpdyFramer framer(spdy_version_);
2531 const char kDescription[] = "Network byte order SETTINGS frame";
2533 const unsigned char kV2FrameData[] = {
2534 0x80, spdy_version_ch_, 0x00, 0x04,
2535 0x00, 0x00, 0x00, 0x0c,
2536 0x00, 0x00, 0x00, 0x01,
2537 0x07, 0x00, 0x00, 0x01,
2538 0x0a, 0x0b, 0x0c, 0x0d,
2540 const unsigned char kV3FrameData[] = {
2541 0x80, spdy_version_ch_, 0x00, 0x04,
2542 0x00, 0x00, 0x00, 0x0c,
2543 0x00, 0x00, 0x00, 0x01,
2544 0x01, 0x00, 0x00, 0x07,
2545 0x0a, 0x0b, 0x0c, 0x0d,
2547 const unsigned char kH2FrameData[] = {
2548 0x00, 0x00, 0x06, 0x04,
2549 0x00, 0x00, 0x00, 0x00,
2550 0x00, 0x00, 0x04, 0x0a,
2551 0x0b, 0x0c, 0x0d,
2554 uint32 kValue = 0x0a0b0c0d;
2555 SpdySettingsIR settings_ir;
2557 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2558 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2559 settings_ir.AddSetting(kId,
2560 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2561 kFlags & SETTINGS_FLAG_PERSISTED,
2562 kValue);
2564 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2565 if (IsSpdy2()) {
2566 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2567 } else if (IsSpdy3()) {
2568 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2569 } else {
2570 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2575 const char kDescription[] = "Basic SETTINGS frame";
2577 const unsigned char kV2FrameData[] = {
2578 0x80, spdy_version_ch_, 0x00, 0x04,
2579 0x00, 0x00, 0x00, 0x24,
2580 0x00, 0x00, 0x00, 0x04,
2581 0x01, 0x00, 0x00, 0x00, // 1st Setting
2582 0x00, 0x00, 0x00, 0x05,
2583 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2584 0x00, 0x00, 0x00, 0x06,
2585 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2586 0x00, 0x00, 0x00, 0x07,
2587 0x04, 0x00, 0x00, 0x00, // 4th Setting
2588 0x00, 0x00, 0x00, 0x08,
2590 const unsigned char kV3FrameData[] = {
2591 0x80, spdy_version_ch_, 0x00, 0x04,
2592 0x00, 0x00, 0x00, 0x24,
2593 0x00, 0x00, 0x00, 0x04,
2594 0x00, 0x00, 0x00, 0x01, // 1st Setting
2595 0x00, 0x00, 0x00, 0x05,
2596 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2597 0x00, 0x00, 0x00, 0x06,
2598 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2599 0x00, 0x00, 0x00, 0x07,
2600 0x00, 0x00, 0x00, 0x04, // 4th Setting
2601 0x00, 0x00, 0x00, 0x08,
2603 // These end up seemingly out of order because of the way that our internal
2604 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2605 // the wire.
2606 const unsigned char kH2FrameData[] = {
2607 0x00, 0x00, 0x18, 0x04,
2608 0x00, 0x00, 0x00, 0x00,
2609 0x00, 0x00, 0x03, // 3rd Setting
2610 0x00, 0x00, 0x00, 0x07,
2611 0x00, 0x04, // 4th Setting
2612 0x00, 0x00, 0x00, 0x08,
2613 0x00, 0x01, // 1st Setting
2614 0x00, 0x00, 0x00, 0x05,
2615 0x00, 0x02, // 2nd Setting
2616 0x00, 0x00, 0x00, 0x06,
2619 SpdySettingsIR settings_ir;
2620 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2621 false, // persist
2622 false, // persisted
2624 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2625 false, // persist
2626 false, // persisted
2628 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2629 false, // persist
2630 false, // persisted
2632 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2633 false, // persist
2634 false, // persisted
2636 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2638 if (IsSpdy2()) {
2639 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2640 } else if (IsSpdy3()) {
2641 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2642 } else {
2643 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2648 const char kDescription[] = "Empty SETTINGS frame";
2650 const unsigned char kV3FrameData[] = { // Also applies for V2.
2651 0x80, spdy_version_ch_, 0x00, 0x04,
2652 0x00, 0x00, 0x00, 0x04,
2653 0x00, 0x00, 0x00, 0x00,
2655 const unsigned char kH2FrameData[] = {
2656 0x00, 0x00, 0x00, 0x04,
2657 0x00, 0x00, 0x00, 0x00,
2658 0x00,
2660 SpdySettingsIR settings_ir;
2661 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2662 if (IsHttp2()) {
2663 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2664 } else {
2665 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2670 TEST_P(SpdyFramerTest, CreatePingFrame) {
2671 SpdyFramer framer(spdy_version_);
2674 const char kDescription[] = "PING frame";
2675 const unsigned char kV3FrameData[] = { // Also applies for V2.
2676 0x80, spdy_version_ch_, 0x00, 0x06,
2677 0x00, 0x00, 0x00, 0x04,
2678 0x12, 0x34, 0x56, 0x78,
2680 const unsigned char kH2FrameData[] = {
2681 0x00, 0x00, 0x08, 0x06,
2682 0x00, 0x00, 0x00, 0x00,
2683 0x00, 0x12, 0x34, 0x56,
2684 0x78, 0x9a, 0xbc, 0xde,
2685 0xff,
2687 const unsigned char kH2FrameDataWithAck[] = {
2688 0x00, 0x00, 0x08, 0x06,
2689 0x01, 0x00, 0x00, 0x00,
2690 0x00, 0x12, 0x34, 0x56,
2691 0x78, 0x9a, 0xbc, 0xde,
2692 0xff,
2694 scoped_ptr<SpdyFrame> frame;
2695 if (IsHttp2()) {
2696 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2697 SpdyPingIR ping_ir(kPingId);
2698 // Tests SpdyPingIR when the ping is not an ack.
2699 ASSERT_FALSE(ping_ir.is_ack());
2700 frame.reset(framer.SerializePing(ping_ir));
2701 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2703 // Tests SpdyPingIR when the ping is an ack.
2704 ping_ir.set_is_ack(true);
2705 frame.reset(framer.SerializePing(ping_ir));
2706 CompareFrame(kDescription, *frame, kH2FrameDataWithAck,
2707 arraysize(kH2FrameDataWithAck));
2709 } else {
2710 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2711 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2716 TEST_P(SpdyFramerTest, CreateGoAway) {
2717 SpdyFramer framer(spdy_version_);
2720 const char kDescription[] = "GOAWAY frame";
2721 const unsigned char kV2FrameData[] = {
2722 0x80, spdy_version_ch_, 0x00, 0x07,
2723 0x00, 0x00, 0x00, 0x04,
2724 0x00, 0x00, 0x00, 0x00, // Stream Id
2726 const unsigned char kV3FrameData[] = {
2727 0x80, spdy_version_ch_, 0x00, 0x07,
2728 0x00, 0x00, 0x00, 0x08,
2729 0x00, 0x00, 0x00, 0x00, // Stream Id
2730 0x00, 0x00, 0x00, 0x00, // Status
2732 const unsigned char kH2FrameData[] = {
2733 0x00, 0x00, 0x0a, 0x07,
2734 0x00, 0x00, 0x00, 0x00,
2735 0x00, 0x00, 0x00, 0x00, // Stream id
2736 0x00, 0x00, 0x00, 0x00, // Status
2737 0x00, 0x47, 0x41, // Opaque Description
2739 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2740 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2741 if (IsSpdy2()) {
2742 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2743 } else if (IsSpdy3()) {
2744 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2745 } else {
2746 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2751 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2752 const unsigned char kV2FrameData[] = {
2753 0x80, spdy_version_ch_, 0x00, 0x07,
2754 0x00, 0x00, 0x00, 0x04,
2755 0x7f, 0xff, 0xff, 0xff, // Stream Id
2757 const unsigned char kV3FrameData[] = {
2758 0x80, spdy_version_ch_, 0x00, 0x07,
2759 0x00, 0x00, 0x00, 0x08,
2760 0x7f, 0xff, 0xff, 0xff, // Stream Id
2761 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2763 const unsigned char kH2FrameData[] = {
2764 0x00, 0x00, 0x0a, 0x07,
2765 0x00, 0x00, 0x00, 0x00,
2766 0x00, 0x7f, 0xff, 0xff, // Stream Id
2767 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2768 0x02, 0x47, 0x41, // Opaque Description
2770 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2771 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2772 if (IsSpdy2()) {
2773 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2774 } else if (IsSpdy3()) {
2775 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2776 } else {
2777 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2782 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2783 SpdyFramer framer(spdy_version_);
2784 framer.set_enable_compression(false);
2787 const char kDescription[] = "HEADERS frame, no FIN";
2789 const unsigned char kV2FrameData[] = {
2790 0x80, spdy_version_ch_, 0x00, 0x08,
2791 0x00, 0x00, 0x00, 0x1C,
2792 0x00, 0x00, 0x00, 0x01,
2793 0x00, 0x00, 0x00, 0x02,
2794 0x00, 0x03, 'b', 'a',
2795 'r', 0x00, 0x03, 'f',
2796 'o', 'o', 0x00, 0x03,
2797 'f', 'o', 'o', 0x00,
2798 0x03, 'b', 'a', 'r'
2800 const unsigned char kV3FrameData[] = {
2801 0x80, spdy_version_ch_, 0x00, 0x08,
2802 0x00, 0x00, 0x00, 0x24,
2803 0x00, 0x00, 0x00, 0x01,
2804 0x00, 0x00, 0x00, 0x02,
2805 0x00, 0x00, 0x00, 0x03,
2806 'b', 'a', 'r', 0x00,
2807 0x00, 0x00, 0x03, 'f',
2808 'o', 'o', 0x00, 0x00,
2809 0x00, 0x03, 'f', 'o',
2810 'o', 0x00, 0x00, 0x00,
2811 0x03, 'b', 'a', 'r'
2813 const unsigned char kH2FrameData[] = {
2814 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2815 0x04, 0x00, 0x00, 0x00, // Stream 1
2816 0x01, 0x00, 0x03, 0x62, // @.ba
2817 0x61, 0x72, 0x03, 0x66, // r.fo
2818 0x6f, 0x6f, 0x00, 0x03, // o@.f
2819 0x66, 0x6f, 0x6f, 0x03, // oo.b
2820 0x62, 0x61, 0x72, // ar
2822 SpdyHeadersIR headers_ir(1);
2823 headers_ir.SetHeader("bar", "foo");
2824 headers_ir.SetHeader("foo", "bar");
2825 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2826 if (IsSpdy2()) {
2827 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2828 } else if (IsSpdy3()) {
2829 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2830 } else {
2831 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2836 const char kDescription[] =
2837 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2839 const unsigned char kV2FrameData[] = {
2840 0x80, spdy_version_ch_, 0x00, 0x08,
2841 0x01, 0x00, 0x00, 0x19,
2842 0x7f, 0xff, 0xff, 0xff,
2843 0x00, 0x00, 0x00, 0x02,
2844 0x00, 0x00, 0x00, 0x03,
2845 'f', 'o', 'o', 0x00,
2846 0x03, 'f', 'o', 'o',
2847 0x00, 0x03, 'b', 'a',
2850 const unsigned char kV3FrameData[] = {
2851 0x80, spdy_version_ch_, 0x00, 0x08,
2852 0x01, 0x00, 0x00, 0x21,
2853 0x7f, 0xff, 0xff, 0xff,
2854 0x00, 0x00, 0x00, 0x02,
2855 0x00, 0x00, 0x00, 0x00,
2856 0x00, 0x00, 0x00, 0x03,
2857 'f', 'o', 'o', 0x00,
2858 0x00, 0x00, 0x03, 'f',
2859 'o', 'o', 0x00, 0x00,
2860 0x00, 0x03, 'b', 'a',
2863 const unsigned char kH2FrameData[] = {
2864 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2865 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2866 0xff, 0x00, 0x00, 0x03, // @..
2867 0x66, 0x6f, 0x6f, 0x00, // foo@
2868 0x03, 0x66, 0x6f, 0x6f, // .foo
2869 0x03, 0x62, 0x61, 0x72, // .bar
2871 SpdyHeadersIR headers_ir(0x7fffffff);
2872 headers_ir.set_fin(true);
2873 headers_ir.SetHeader("", "foo");
2874 headers_ir.SetHeader("foo", "bar");
2875 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2876 if (IsSpdy2()) {
2877 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2878 } else if (IsSpdy3()) {
2879 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2880 } else {
2881 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2886 const char kDescription[] =
2887 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2889 const unsigned char kV2FrameData[] = {
2890 0x80, spdy_version_ch_, 0x00, 0x08,
2891 0x01, 0x00, 0x00, 0x19,
2892 0x7f, 0xff, 0xff, 0xff,
2893 0x00, 0x00, 0x00, 0x02,
2894 0x00, 0x03, 'b', 'a',
2895 'r', 0x00, 0x03, 'f',
2896 'o', 'o', 0x00, 0x03,
2897 'f', 'o', 'o', 0x00,
2898 0x00
2900 const unsigned char kV3FrameData[] = {
2901 0x80, spdy_version_ch_, 0x00, 0x08,
2902 0x01, 0x00, 0x00, 0x21,
2903 0x7f, 0xff, 0xff, 0xff,
2904 0x00, 0x00, 0x00, 0x02,
2905 0x00, 0x00, 0x00, 0x03,
2906 'b', 'a', 'r', 0x00,
2907 0x00, 0x00, 0x03, 'f',
2908 'o', 'o', 0x00, 0x00,
2909 0x00, 0x03, 'f', 'o',
2910 'o', 0x00, 0x00, 0x00,
2911 0x00
2913 const unsigned char kH2FrameData[] = {
2914 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2915 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2916 0xff, 0x00, 0x03, 0x62, // @.b
2917 0x61, 0x72, 0x03, 0x66, // ar.f
2918 0x6f, 0x6f, 0x00, 0x03, // oo@.
2919 0x66, 0x6f, 0x6f, 0x00, // foo.
2921 SpdyHeadersIR headers_ir(0x7fffffff);
2922 headers_ir.set_fin(true);
2923 headers_ir.SetHeader("bar", "foo");
2924 headers_ir.SetHeader("foo", "");
2925 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2926 if (IsSpdy2()) {
2927 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2928 } else if (IsSpdy3()) {
2929 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2930 } else {
2931 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2936 const char kDescription[] =
2937 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2939 const unsigned char kH2FrameData[] = {
2940 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2941 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2942 0xff, 0x00, 0x00, 0x00, // exclusive, parent stream
2943 0x00, 0xdb, // weight
2944 0x00, 0x03, 0x62, 0x61, // @.ba
2945 0x72, 0x03, 0x66, 0x6f, // r.fo
2946 0x6f, 0x00, 0x03, 0x66, // o@.f
2947 0x6f, 0x6f, 0x00, // oo.
2949 SpdyHeadersIR headers_ir(0x7fffffff);
2950 headers_ir.set_fin(true);
2951 headers_ir.set_priority(1);
2952 headers_ir.set_has_priority(true);
2953 headers_ir.SetHeader("bar", "foo");
2954 headers_ir.SetHeader("foo", "");
2955 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2956 if (IsSpdy2() || IsSpdy3()) {
2957 // HEADERS with priority not supported.
2958 } else {
2959 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2964 const char kDescription[] =
2965 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2966 "exclusive=true, parent_stream=0";
2968 const unsigned char kH2FrameData[] = {
2969 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2970 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2971 0xff, 0x80, 0x00, 0x00, // exclusive, parent stream
2972 0x00, 0xdb, // weight
2973 0x00, 0x03, 0x62, 0x61, // @.ba
2974 0x72, 0x03, 0x66, 0x6f, // r.fo
2975 0x6f, 0x00, 0x03, 0x66, // o@.f
2976 0x6f, 0x6f, 0x00, // oo.
2978 SpdyHeadersIR headers_ir(0x7fffffff);
2979 headers_ir.set_fin(true);
2980 headers_ir.set_priority(1);
2981 headers_ir.set_has_priority(true);
2982 headers_ir.set_exclusive(true);
2983 headers_ir.set_parent_stream_id(0);
2984 headers_ir.SetHeader("bar", "foo");
2985 headers_ir.SetHeader("foo", "");
2986 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2987 if (IsSpdy2() || IsSpdy3()) {
2988 // HEADERS with priority not supported.
2989 } else {
2990 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2995 const char kDescription[] =
2996 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2997 "exclusive=false, parent_stream=max stream ID";
2999 const unsigned char kH2FrameData[] = {
3000 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
3001 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
3002 0xff, 0x7f, 0xff, 0xff, // exclusive, parent stream
3003 0xff, 0xdb, // weight
3004 0x00, 0x03, 0x62, 0x61, // @.ba
3005 0x72, 0x03, 0x66, 0x6f, // r.fo
3006 0x6f, 0x00, 0x03, 0x66, // o@.f
3007 0x6f, 0x6f, 0x00, // oo.
3009 SpdyHeadersIR headers_ir(0x7fffffff);
3010 headers_ir.set_fin(true);
3011 headers_ir.set_priority(1);
3012 headers_ir.set_has_priority(true);
3013 headers_ir.set_exclusive(false);
3014 headers_ir.set_parent_stream_id(0x7fffffff);
3015 headers_ir.SetHeader("bar", "foo");
3016 headers_ir.SetHeader("foo", "");
3017 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3018 if (IsSpdy2() || IsSpdy3()) {
3019 // HEADERS with priority not supported.
3020 } else {
3021 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3026 const char kDescription[] =
3027 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
3029 const unsigned char kH2FrameData[] = {
3030 0x00, 0x00, 0x15, 0x01, // Headers
3031 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
3032 // 0x7fffffff
3033 0xff, 0x05, 0x00, 0x00, // Pad length field
3034 0x03, 0x66, 0x6f, 0x6f, // .foo
3035 0x00, 0x03, 0x66, 0x6f, // @.fo
3036 0x6f, 0x03, 0x62, 0x61, // o.ba
3037 0x72, // r
3038 // Padding payload
3039 0x00, 0x00, 0x00, 0x00, 0x00,
3041 SpdyHeadersIR headers_ir(0x7fffffff);
3042 headers_ir.set_fin(true);
3043 headers_ir.SetHeader("", "foo");
3044 headers_ir.SetHeader("foo", "bar");
3045 headers_ir.set_padding_len(6);
3046 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3047 if (IsSpdy2() || IsSpdy3()) {
3048 // Padding is not supported.
3049 } else {
3050 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3055 // TODO(phajdan.jr): Clean up after we no longer need
3056 // to workaround http://crbug.com/139744.
3057 #if !defined(USE_SYSTEM_ZLIB)
3058 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
3059 SpdyFramer framer(spdy_version_);
3060 framer.set_enable_compression(true);
3063 const char kDescription[] = "HEADERS frame, no FIN";
3065 const unsigned char kV2FrameData[] = {
3066 0x80, spdy_version_ch_, 0x00, 0x08,
3067 0x00, 0x00, 0x00, 0x32,
3068 0x00, 0x00, 0x00, 0x01,
3069 0x00, 0x00, 0x38, 0xea,
3070 0xdf, 0xa2, 0x51, 0xb2,
3071 0x62, 0x60, 0x62, 0x60,
3072 0x4e, 0x4a, 0x2c, 0x62,
3073 0x60, 0x06, 0x08, 0xa0,
3074 0xb4, 0xfc, 0x7c, 0x80,
3075 0x00, 0x62, 0x60, 0x4e,
3076 0xcb, 0xcf, 0x67, 0x60,
3077 0x06, 0x08, 0xa0, 0xa4,
3078 0xc4, 0x22, 0x80, 0x00,
3079 0x02, 0x00, 0x00, 0x00,
3080 0xff, 0xff,
3082 const unsigned char kV3FrameData[] = {
3083 0x80, spdy_version_ch_, 0x00, 0x08,
3084 0x00, 0x00, 0x00, 0x31,
3085 0x00, 0x00, 0x00, 0x01,
3086 0x38, 0xea, 0xe3, 0xc6,
3087 0xa7, 0xc2, 0x02, 0xe5,
3088 0x0e, 0x50, 0xc2, 0x4b,
3089 0x4a, 0x04, 0xe5, 0x0b,
3090 0x66, 0x80, 0x00, 0x4a,
3091 0xcb, 0xcf, 0x07, 0x08,
3092 0x20, 0x10, 0x95, 0x96,
3093 0x9f, 0x0f, 0xa2, 0x00,
3094 0x02, 0x28, 0x29, 0xb1,
3095 0x08, 0x20, 0x80, 0x00,
3096 0x00, 0x00, 0x00, 0xff,
3097 0xff,
3099 const unsigned char kV2SIMDFrameData[] = {
3100 0x80, spdy_version_ch_, 0x00, 0x08,
3101 0x00, 0x00, 0x00, 0x2f,
3102 0x00, 0x00, 0x00, 0x01,
3103 0x00, 0x00, 0x38, 0xea,
3104 0xdf, 0xa2, 0x51, 0xb2,
3105 0x62, 0x60, 0x62, 0x60,
3106 0x4e, 0x4a, 0x2c, 0x62,
3107 0x60, 0x06, 0x08, 0xa0,
3108 0xb4, 0xfc, 0x7c, 0x80,
3109 0x00, 0x62, 0x60, 0x06,
3110 0x13, 0x00, 0x01, 0x94,
3111 0x94, 0x58, 0x04, 0x10,
3112 0x40, 0x00, 0x00, 0x00,
3113 0x00, 0xff, 0xff,
3115 const unsigned char kV3SIMDFrameData[] = {
3116 0x80, spdy_version_ch_, 0x00, 0x08,
3117 0x00, 0x00, 0x00, 0x2c,
3118 0x00, 0x00, 0x00, 0x01,
3119 0x38, 0xea, 0xe3, 0xc6,
3120 0xa7, 0xc2, 0x02, 0xe5,
3121 0x0e, 0x50, 0xc2, 0x4b,
3122 0x4a, 0x04, 0xe5, 0x0b,
3123 0x66, 0x80, 0x00, 0x4a,
3124 0xcb, 0xcf, 0x07, 0x08,
3125 0x20, 0x24, 0x0a, 0x20,
3126 0x80, 0x92, 0x12, 0x8b,
3127 0x00, 0x02, 0x08, 0x00,
3128 0x00, 0x00, 0xff, 0xff,
3131 SpdyHeadersIR headers_ir(1);
3132 headers_ir.SetHeader("bar", "foo");
3133 headers_ir.SetHeader("foo", "bar");
3134 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3135 const unsigned char* frame_data =
3136 reinterpret_cast<const unsigned char*>(frame->data());
3137 if (IsSpdy2()) {
3138 // Try comparing with SIMD version, if that fails, do a failing check
3139 // with pretty printing against non-SIMD version
3140 if (memcmp(frame_data,
3141 kV2SIMDFrameData,
3142 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3143 CompareCharArraysWithHexError(kDescription,
3144 frame_data,
3145 frame->size(),
3146 kV2FrameData,
3147 arraysize(kV2FrameData));
3149 } else if (IsSpdy3()) {
3150 if (memcmp(frame_data,
3151 kV3SIMDFrameData,
3152 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3153 CompareCharArraysWithHexError(kDescription,
3154 frame_data,
3155 frame->size(),
3156 kV3FrameData,
3157 arraysize(kV3FrameData));
3159 } else {
3160 // Deflate compression doesn't apply to HPACK.
3164 #endif // !defined(USE_SYSTEM_ZLIB)
3166 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3167 SpdyFramer framer(spdy_version_);
3170 const char kDescription[] = "WINDOW_UPDATE frame";
3171 const unsigned char kV3FrameData[] = { // Also applies for V2.
3172 0x80, spdy_version_ch_, 0x00, 0x09,
3173 0x00, 0x00, 0x00, 0x08,
3174 0x00, 0x00, 0x00, 0x01,
3175 0x00, 0x00, 0x00, 0x01,
3177 const unsigned char kH2FrameData[] = {
3178 0x00, 0x00, 0x04, 0x08,
3179 0x00, 0x00, 0x00, 0x00,
3180 0x01, 0x00, 0x00, 0x00,
3181 0x01,
3183 scoped_ptr<SpdyFrame> frame(
3184 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3185 if (IsHttp2()) {
3186 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3187 } else {
3188 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3193 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3194 const unsigned char kV3FrameData[] = { // Also applies for V2.
3195 0x80, spdy_version_ch_, 0x00, 0x09,
3196 0x00, 0x00, 0x00, 0x08,
3197 0x7f, 0xff, 0xff, 0xff,
3198 0x00, 0x00, 0x00, 0x01,
3200 const unsigned char kH2FrameData[] = {
3201 0x00, 0x00, 0x04, 0x08,
3202 0x00, 0x7f, 0xff, 0xff,
3203 0xff, 0x00, 0x00, 0x00,
3204 0x01,
3206 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3207 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3208 if (IsHttp2()) {
3209 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3210 } else {
3211 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3216 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3217 const unsigned char kV3FrameData[] = { // Also applies for V2.
3218 0x80, spdy_version_ch_, 0x00, 0x09,
3219 0x00, 0x00, 0x00, 0x08,
3220 0x00, 0x00, 0x00, 0x01,
3221 0x7f, 0xff, 0xff, 0xff,
3223 const unsigned char kH2FrameData[] = {
3224 0x00, 0x00, 0x04, 0x08,
3225 0x00, 0x00, 0x00, 0x00,
3226 0x01, 0x7f, 0xff, 0xff,
3227 0xff,
3229 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3230 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3231 if (IsHttp2()) {
3232 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3233 } else {
3234 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3239 TEST_P(SpdyFramerTest, SerializeBlocked) {
3240 if (spdy_version_ <= SPDY3) {
3241 return;
3244 SpdyFramer framer(spdy_version_);
3246 const char kDescription[] = "BLOCKED frame";
3247 const unsigned char kType = static_cast<unsigned char>(
3248 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3249 const unsigned char kFrameData[] = {
3250 0x00, 0x00, 0x00, kType, 0x00,
3251 0x00, 0x00, 0x00, 0x00,
3253 SpdyBlockedIR blocked_ir(0);
3254 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3255 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3258 TEST_P(SpdyFramerTest, CreateBlocked) {
3259 if (spdy_version_ <= SPDY3) {
3260 return;
3263 SpdyFramer framer(spdy_version_);
3265 const char kDescription[] = "BLOCKED frame";
3266 const SpdyStreamId kStreamId = 3;
3268 scoped_ptr<SpdySerializedFrame> frame_serialized(
3269 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3270 SpdyBlockedIR blocked_ir(kStreamId);
3271 scoped_ptr<SpdySerializedFrame> frame_created(
3272 framer.SerializeFrame(blocked_ir));
3274 CompareFrames(kDescription, *frame_serialized, *frame_created);
3277 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3278 if (spdy_version_ <= SPDY3) {
3279 return;
3283 // Test framing PUSH_PROMISE without padding.
3284 SpdyFramer framer(spdy_version_);
3285 framer.set_enable_compression(false);
3286 const char kDescription[] = "PUSH_PROMISE frame without padding";
3288 const unsigned char kFrameData[] = {
3289 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3290 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3291 0x2a, 0x00, 0x00, 0x00, // Stream 42
3292 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3293 0x61, 0x72, 0x03, 0x66, // ar.f
3294 0x6f, 0x6f, 0x00, 0x03, // oo@.
3295 0x66, 0x6f, 0x6f, 0x03, // foo.
3296 0x62, 0x61, 0x72, // bar
3299 SpdyPushPromiseIR push_promise(42, 57);
3300 push_promise.SetHeader("bar", "foo");
3301 push_promise.SetHeader("foo", "bar");
3302 scoped_ptr<SpdySerializedFrame> frame(
3303 framer.SerializePushPromise(push_promise));
3304 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3308 // Test framing PUSH_PROMISE with one byte of padding.
3309 SpdyFramer framer(spdy_version_);
3310 framer.set_enable_compression(false);
3311 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3313 const unsigned char kFrameData[] = {
3314 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3315 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3316 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3317 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3318 0x62, 0x61, 0x72, 0x03, // bar.
3319 0x66, 0x6f, 0x6f, 0x00, // foo@
3320 0x03, 0x66, 0x6f, 0x6f, // .foo
3321 0x03, 0x62, 0x61, 0x72, // .bar
3324 SpdyPushPromiseIR push_promise(42, 57);
3325 push_promise.set_padding_len(1);
3326 push_promise.SetHeader("bar", "foo");
3327 push_promise.SetHeader("foo", "bar");
3328 scoped_ptr<SpdySerializedFrame> frame(
3329 framer.SerializePushPromise(push_promise));
3330 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3334 // Test framing PUSH_PROMISE with 177 bytes of padding.
3335 SpdyFramer framer(spdy_version_);
3336 framer.set_enable_compression(false);
3337 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3339 const unsigned char kFrameData[] = {
3340 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3341 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3342 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3343 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3344 0x62, 0x61, 0x72, 0x03, // bar.
3345 0x66, 0x6f, 0x6f, 0x00, // foo@
3346 0x03, 0x66, 0x6f, 0x6f, // .foo
3347 0x03, 0x62, 0x61, 0x72, // .bar
3348 // Padding of 176 0x00(s).
3349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3366 SpdyPushPromiseIR push_promise(42, 57);
3367 push_promise.set_padding_len(177);
3368 push_promise.SetHeader("bar", "foo");
3369 push_promise.SetHeader("foo", "bar");
3370 scoped_ptr<SpdySerializedFrame> frame(
3371 framer.SerializePushPromise(push_promise));
3372 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3376 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
3377 if (spdy_version_ <= SPDY3) {
3378 return;
3381 SpdyFramer framer(spdy_version_);
3382 // Test case from https://crbug.com/464748.
3383 EXPECT_EQ(1u,
3384 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2039));
3385 EXPECT_EQ(2u,
3386 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2040));
3389 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3390 if (spdy_version_ <= SPDY3) {
3391 return;
3394 SpdyFramer framer(spdy_version_);
3395 framer.set_enable_compression(false);
3396 const char kDescription[] = "CONTINUATION frame";
3398 const unsigned char kFrameData[] = {
3399 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3400 0x04, 0x00, 0x00, 0x00, // end_headers = true
3401 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3402 0x61, 0x72, 0x03, 0x66, // ar.f
3403 0x6f, 0x6f, 0x00, 0x03, // oo@.
3404 0x66, 0x6f, 0x6f, 0x03, // foo.
3405 0x62, 0x61, 0x72, // bar
3408 SpdyContinuationIR continuation(42);
3409 continuation.SetHeader("bar", "foo");
3410 continuation.SetHeader("foo", "bar");
3411 continuation.set_end_headers(true);
3412 scoped_ptr<SpdySerializedFrame> frame(
3413 framer.SerializeContinuation(continuation));
3414 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3417 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3418 if (spdy_version_ <= SPDY3) {
3419 return;
3423 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3424 // padding, cannot hold all the data payload, which is overflowed to the
3425 // consecutive CONTINUATION frame.
3426 SpdyFramer framer(spdy_version_);
3427 framer.set_enable_compression(false);
3428 const char kDescription[] =
3429 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3431 const unsigned char kPartialPushPromiseFrameData[] = {
3432 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3433 0x08, 0x00, 0x00, 0x00, // PADDED
3434 0x2a, 0x00, 0x00, 0x00, // Stream 42
3435 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3436 0x78, 0x78, 0x78, 0x7f, // xxx.
3437 0x81, 0x07, 0x78, 0x78, // ..xx
3438 0x78, 0x78, 0x78, 0x78, // xxxx
3439 0x78, 0x78, 0x78, 0x78, // xxxx
3440 0x78, 0x78, 0x78, 0x78, // xxxx
3441 0x78, 0x78, 0x78, 0x78, // xxxx
3442 0x78, 0x78, 0x78, 0x78, // xxxx
3443 0x78, 0x78, 0x78, 0x78, // xxxx
3444 0x78, 0x78, 0x78, 0x78, // xxxx
3445 0x78, 0x78, 0x78, 0x78, // xxxx
3446 0x78, 0x78, 0x78, 0x78, // xxxx
3447 0x78, 0x78, 0x78, 0x78, // xxxx
3448 0x78, 0x78, 0x78, 0x78, // xxxx
3449 0x78, 0x78, 0x78, 0x78, // xxxx
3450 0x78, 0x78, 0x78, 0x78, // xxxx
3451 0x78, 0x78, 0x78, 0x78, // xxxx
3452 0x78, 0x78, 0x78, 0x78, // xxxx
3453 0x78, 0x78, 0x78, 0x78, // xxxx
3454 0x78, 0x78, 0x78, 0x78, // xxxx
3455 0x78, 0x78, 0x78, 0x78, // xxxx
3456 0x78, 0x78, 0x78, 0x78, // xxxx
3457 0x78, 0x78, 0x78, 0x78, // xxxx
3458 0x78, 0x78, // xx
3461 const unsigned char kContinuationFrameData[] = {
3462 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3463 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3464 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3465 0x78, 0x78, 0x78, 0x78, // xxxx
3466 0x78, 0x78, 0x78, 0x78, // xxxx
3467 0x78, 0x78, 0x78, 0x78, // xxxx
3468 0x78, 0x78, 0x78, 0x78, // xxxx
3469 0x78, 0x78,
3472 SpdyPushPromiseIR push_promise(42, 57);
3473 push_promise.set_padding_len(1);
3474 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3475 push_promise.SetHeader("xxx", big_value);
3476 scoped_ptr<SpdySerializedFrame> frame(
3477 framer.SerializePushPromise(push_promise));
3479 // The entire frame should look like below:
3480 // Name Length in Byte
3481 // ------------------------------------------- Begin of PUSH_PROMISE frame
3482 // PUSH_PROMISE header 9
3483 // Pad length field 1
3484 // Promised stream 4
3485 // Length field of key 2
3486 // Content of key 3
3487 // Length field of value 3
3488 // Part of big_value 16361
3489 // ------------------------------------------- Begin of CONTINUATION frame
3490 // CONTINUATION header 9
3491 // Remaining of big_value 22
3492 // ------------------------------------------- End
3494 // Length of everything listed above except big_value.
3495 int len_non_data_payload = 31;
3496 EXPECT_EQ(
3497 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3498 frame->size());
3500 // Partially compare the PUSH_PROMISE frame against the template.
3501 const unsigned char* frame_data =
3502 reinterpret_cast<const unsigned char*>(frame->data());
3503 CompareCharArraysWithHexError(kDescription,
3504 frame_data,
3505 arraysize(kPartialPushPromiseFrameData),
3506 kPartialPushPromiseFrameData,
3507 arraysize(kPartialPushPromiseFrameData));
3509 // Compare the CONTINUATION frame against the template.
3510 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3511 CompareCharArraysWithHexError(kDescription,
3512 frame_data,
3513 arraysize(kContinuationFrameData),
3514 kContinuationFrameData,
3515 arraysize(kContinuationFrameData));
3519 TEST_P(SpdyFramerTest, CreateAltSvc) {
3520 if (spdy_version_ <= SPDY3) {
3521 return;
3524 SpdyFramer framer(spdy_version_);
3526 const char kDescription[] = "ALTSVC frame";
3527 const char kType = static_cast<unsigned char>(
3528 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3529 const unsigned char kFrameData[] = {
3530 0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
3531 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h',
3532 'o', 's', 't', ':', '4', '4', '3', '"', ';', ' ', 'm', 'a',
3533 '=', '5', ',', 'p', '%', '2', '2', '%', '3', 'D', 'i', '%',
3534 '3', 'A', 'd', '=', '"', 'h', '_', '\\', '\\', 'o', '\\', '"',
3535 's', 't', ':', '1', '2', '3', '"', ';', ' ', 'm', 'a', '=',
3536 '4', '2', ';', ' ', 'p', '=', '0', '.', '2', '0',
3538 SpdyAltSvcIR altsvc_ir(3);
3539 altsvc_ir.set_origin("origin");
3540 altsvc_ir.add_altsvc(
3541 SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0));
3542 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
3543 "p\"=i:d", "h_\\o\"st", 123, 42, 0.2));
3544 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3545 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3548 TEST_P(SpdyFramerTest, CreatePriority) {
3549 if (spdy_version_ <= SPDY3) {
3550 return;
3553 SpdyFramer framer(spdy_version_);
3555 const char kDescription[] = "PRIORITY frame";
3556 const unsigned char kType = static_cast<unsigned char>(
3557 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3558 const unsigned char kFrameData[] = {
3559 0x00, 0x00, 0x05, kType, 0x00,
3560 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3561 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3562 0x10, // Weight = 16
3564 SpdyPriorityIR priority_ir(2, 1, 16, true);
3565 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3566 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3567 SpdyPriorityIR priority2(2);
3568 priority2.set_parent_stream_id(1);
3569 priority2.set_weight(16);
3570 priority2.set_exclusive(true);
3571 frame.reset(framer.SerializeFrame(priority2));
3572 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3575 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3576 if (spdy_version_ > SPDY3) {
3577 // SYN_STREAM not supported in SPDY>3
3578 return;
3580 SpdyFramer framer(spdy_version_);
3581 SpdySynStreamIR syn_stream(1);
3582 syn_stream.set_priority(1);
3583 syn_stream.SetHeader("aa", "vv");
3584 syn_stream.SetHeader("bb", "ww");
3585 SpdyHeaderBlock headers = syn_stream.name_value_block();
3586 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3587 EXPECT_TRUE(control_frame.get() != NULL);
3588 TestSpdyVisitor visitor(spdy_version_);
3589 visitor.use_compression_ = true;
3590 visitor.SimulateInFramer(
3591 reinterpret_cast<unsigned char*>(control_frame->data()),
3592 control_frame->size());
3593 EXPECT_EQ(1, visitor.syn_frame_count_);
3594 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3597 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3598 if (spdy_version_ > SPDY3) {
3599 return;
3601 SpdyFramer framer(spdy_version_);
3602 SpdySynReplyIR syn_reply(1);
3603 syn_reply.SetHeader("alpha", "beta");
3604 syn_reply.SetHeader("gamma", "delta");
3605 SpdyHeaderBlock headers = syn_reply.name_value_block();
3606 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3607 EXPECT_TRUE(control_frame.get() != NULL);
3608 TestSpdyVisitor visitor(spdy_version_);
3609 visitor.use_compression_ = true;
3610 visitor.SimulateInFramer(
3611 reinterpret_cast<unsigned char*>(control_frame->data()),
3612 control_frame->size());
3613 if (IsHttp2()) {
3614 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3615 EXPECT_EQ(1, visitor.headers_frame_count_);
3616 } else {
3617 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3618 EXPECT_EQ(0, visitor.headers_frame_count_);
3620 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3623 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3624 SpdyFramer framer(spdy_version_);
3625 SpdyHeadersIR headers_ir(1);
3626 headers_ir.SetHeader("alpha", "beta");
3627 headers_ir.SetHeader("gamma", "delta");
3628 SpdyHeaderBlock headers = headers_ir.name_value_block();
3629 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3630 EXPECT_TRUE(control_frame.get() != NULL);
3631 TestSpdyVisitor visitor(spdy_version_);
3632 visitor.use_compression_ = true;
3633 visitor.SimulateInFramer(
3634 reinterpret_cast<unsigned char*>(control_frame->data()),
3635 control_frame->size());
3636 EXPECT_EQ(1, visitor.headers_frame_count_);
3637 // control_frame_header_data_count_ depends on the random sequence
3638 // produced by rand(), so adding, removing or running single tests
3639 // alters this value. The best we can do is assert that it happens
3640 // at least twice.
3641 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3642 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3643 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3644 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3647 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3648 SpdyFramer framer(spdy_version_);
3649 SpdyHeadersIR headers_ir(1);
3650 headers_ir.set_fin(true);
3651 headers_ir.SetHeader("alpha", "beta");
3652 headers_ir.SetHeader("gamma", "delta");
3653 SpdyHeaderBlock headers = headers_ir.name_value_block();
3654 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3655 EXPECT_TRUE(control_frame.get() != NULL);
3656 TestSpdyVisitor visitor(spdy_version_);
3657 visitor.use_compression_ = true;
3658 visitor.SimulateInFramer(
3659 reinterpret_cast<unsigned char*>(control_frame->data()),
3660 control_frame->size());
3661 EXPECT_EQ(1, visitor.headers_frame_count_);
3662 // control_frame_header_data_count_ depends on the random sequence
3663 // produced by rand(), so adding, removing or running single tests
3664 // alters this value. The best we can do is assert that it happens
3665 // at least twice.
3666 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3667 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3668 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3669 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3672 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3673 if (spdy_version_ > SPDY3) {
3674 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3675 return;
3677 // First find the size of the header value in order to just reach the control
3678 // frame max size.
3679 SpdyFramer framer(spdy_version_);
3680 framer.set_enable_compression(false);
3681 SpdySynStreamIR syn_stream(1);
3682 syn_stream.set_priority(1);
3683 syn_stream.SetHeader("aa", "");
3684 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3685 const size_t kBigValueSize =
3686 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3688 // Create a frame at exactly that size.
3689 string big_value(kBigValueSize, 'x');
3690 syn_stream.SetHeader("aa", big_value);
3691 control_frame.reset(framer.SerializeSynStream(syn_stream));
3692 EXPECT_TRUE(control_frame.get() != NULL);
3693 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3694 control_frame->size());
3696 TestSpdyVisitor visitor(spdy_version_);
3697 visitor.SimulateInFramer(
3698 reinterpret_cast<unsigned char*>(control_frame->data()),
3699 control_frame->size());
3700 EXPECT_TRUE(visitor.header_buffer_valid_);
3701 EXPECT_EQ(0, visitor.error_count_);
3702 EXPECT_EQ(1, visitor.syn_frame_count_);
3703 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3704 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3705 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3708 TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
3709 if (spdy_version_ > SPDY3) {
3710 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3711 return;
3713 if (spdy_version_ < SPDY3) {
3714 // Since SPDY/2 uses 16 bit header field lengths, one cannot easily create a
3715 // header frame of maximum size.
3716 return;
3718 // First find the size of the header value in order to just reach the control
3719 // frame max size.
3720 SpdyFramer framer(spdy_version_);
3721 framer.set_enable_compression(false);
3722 SpdySynStreamIR syn_stream(1);
3723 syn_stream.SetHeader("aa", "");
3724 syn_stream.set_priority(1);
3725 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3726 const size_t kBigValueSize =
3727 SpdyConstants::GetFrameMaximumSize(spdy_version_) - control_frame->size();
3729 // Create a frame at exatly that size.
3730 string big_value(kBigValueSize, 'x');
3731 syn_stream.SetHeader("aa", big_value);
3732 // Upstream branches here and wraps HTTP/2 with EXPECT_DEBUG_DFATAL. We
3733 // neither support that in Chromium, nor do we use the same DFATAL (see
3734 // SpdyFrameBuilder::WriteFramePrefix()).
3735 control_frame.reset(framer.SerializeSynStream(syn_stream));
3737 EXPECT_TRUE(control_frame.get() != NULL);
3738 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_),
3739 control_frame->size());
3741 TestSpdyVisitor visitor(spdy_version_);
3742 visitor.SimulateInFramer(
3743 reinterpret_cast<unsigned char*>(control_frame->data()),
3744 control_frame->size());
3745 EXPECT_TRUE(visitor.header_buffer_valid_);
3746 EXPECT_EQ(0, visitor.error_count_);
3747 EXPECT_EQ(1, visitor.syn_frame_count_);
3750 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3751 if (spdy_version_ <= SPDY3) {
3752 return;
3754 SpdyFramer framer(spdy_version_);
3755 framer.set_enable_compression(false);
3756 SpdyHeadersIR headers(1);
3757 headers.set_padding_len(256);
3759 // Exact payload length will change with HPACK, but this should be long
3760 // enough to cause an overflow.
3761 const size_t kBigValueSize = kControlFrameSizeLimit;
3762 string big_value(kBigValueSize, 'x');
3763 headers.SetHeader("aa", big_value);
3764 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3765 EXPECT_TRUE(control_frame.get() != NULL);
3766 EXPECT_GT(control_frame->size(),
3767 TestSpdyVisitor::sent_control_frame_max_size());
3769 TestSpdyVisitor visitor(spdy_version_);
3770 visitor.SimulateInFramer(
3771 reinterpret_cast<unsigned char*>(control_frame->data()),
3772 control_frame->size());
3773 EXPECT_TRUE(visitor.header_buffer_valid_);
3774 EXPECT_EQ(0, visitor.error_count_);
3775 EXPECT_EQ(1, visitor.headers_frame_count_);
3776 EXPECT_EQ(16, visitor.continuation_count_);
3777 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3780 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3781 if (spdy_version_ <= SPDY3) {
3782 return;
3784 SpdyFramer framer(spdy_version_);
3785 framer.set_enable_compression(false);
3786 SpdyPushPromiseIR push_promise(1, 2);
3787 push_promise.set_padding_len(256);
3789 // Exact payload length will change with HPACK, but this should be long
3790 // enough to cause an overflow.
3791 const size_t kBigValueSize = kControlFrameSizeLimit;
3792 string big_value(kBigValueSize, 'x');
3793 push_promise.SetHeader("aa", big_value);
3794 scoped_ptr<SpdyFrame> control_frame(
3795 framer.SerializePushPromise(push_promise));
3796 EXPECT_TRUE(control_frame.get() != NULL);
3797 EXPECT_GT(control_frame->size(),
3798 TestSpdyVisitor::sent_control_frame_max_size());
3800 TestSpdyVisitor visitor(spdy_version_);
3801 visitor.SimulateInFramer(
3802 reinterpret_cast<unsigned char*>(control_frame->data()),
3803 control_frame->size());
3804 EXPECT_TRUE(visitor.header_buffer_valid_);
3805 EXPECT_EQ(0, visitor.error_count_);
3806 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3807 EXPECT_EQ(16, visitor.continuation_count_);
3808 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3811 // Check that the framer stops delivering header data chunks once the visitor
3812 // declares it doesn't want any more. This is important to guard against
3813 // "zip bomb" types of attacks.
3814 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3815 const size_t kHeaderBufferChunks = 4;
3816 const size_t kHeaderBufferSize =
3817 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3818 const size_t kBigValueSize = kHeaderBufferSize * 2;
3819 string big_value(kBigValueSize, 'x');
3820 SpdyFramer framer(spdy_version_);
3821 SpdyHeadersIR headers(1);
3822 headers.set_priority(1);
3823 headers.set_fin(true);
3824 headers.SetHeader("aa", big_value);
3825 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3826 EXPECT_TRUE(control_frame.get() != NULL);
3827 TestSpdyVisitor visitor(spdy_version_);
3828 visitor.set_header_buffer_size(kHeaderBufferSize);
3829 visitor.use_compression_ = true;
3830 visitor.SimulateInFramer(
3831 reinterpret_cast<unsigned char*>(control_frame->data()),
3832 control_frame->size());
3833 EXPECT_FALSE(visitor.header_buffer_valid_);
3834 EXPECT_EQ(1, visitor.error_count_);
3835 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3836 visitor.framer_.error_code())
3837 << SpdyFramer::ErrorCodeToString(framer.error_code());
3839 // The framer should have stoped delivering chunks after the visitor
3840 // signaled "stop" by returning false from OnControlFrameHeaderData().
3842 // control_frame_header_data_count_ depends on the random sequence
3843 // produced by rand(), so adding, removing or running single tests
3844 // alters this value. The best we can do is assert that it happens
3845 // at least kHeaderBufferChunks + 1.
3846 EXPECT_LE(kHeaderBufferChunks + 1,
3847 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3848 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3850 // The framer should not have sent half-close to the visitor.
3851 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3854 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3855 if (spdy_version_ > SPDY3) {
3856 // Deflate compression doesn't apply to HPACK.
3857 return;
3859 SpdyFramer framer(spdy_version_);
3860 framer.set_enable_compression(false);
3861 // Construct a SYN_STREAM control frame without compressing the header block,
3862 // and have the framer try to decompress it. This will cause the framer to
3863 // deal with a decompression error.
3864 SpdySynStreamIR syn_stream(1);
3865 syn_stream.set_priority(1);
3866 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3867 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3868 TestSpdyVisitor visitor(spdy_version_);
3869 visitor.use_compression_ = true;
3870 visitor.SimulateInFramer(
3871 reinterpret_cast<unsigned char*>(control_frame->data()),
3872 control_frame->size());
3873 EXPECT_EQ(1, visitor.error_count_);
3874 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3875 << SpdyFramer::ErrorCodeToString(framer.error_code());
3876 EXPECT_EQ(0u, visitor.header_buffer_length_);
3879 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3880 SpdyFramer framer(spdy_version_);
3881 // Create a GoAway frame that has a few extra bytes at the end.
3882 // We create enough overhead to overflow the framer's control frame buffer.
3883 ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
3884 const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
3885 const unsigned char kV3FrameData[] = { // Also applies for V2.
3886 0x80, spdy_version_ch_, 0x00, 0x07,
3887 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
3888 0x00, 0x00, 0x00, 0x00, // Stream ID
3889 0x00, 0x00, 0x00, 0x00, // Status
3892 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3893 // since it may carry opaque data. Verify that minimal length is tested.
3894 ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
3895 const size_t less_than_min_length =
3896 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3897 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3898 const unsigned char kH2FrameData[] = {
3899 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
3900 0x00, 0x00, 0x00, 0x00,
3901 0x00, 0x00, 0x00, 0x00, // Stream Id
3902 0x00, 0x00, 0x00, 0x00, // Status
3903 0x00,
3905 const size_t pad_length =
3906 length + framer.GetControlFrameHeaderSize() -
3907 (IsHttp2() ? sizeof(kH2FrameData) : sizeof(kV3FrameData));
3908 string pad(pad_length, 'A');
3909 TestSpdyVisitor visitor(spdy_version_);
3911 if (IsHttp2()) {
3912 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3913 } else {
3914 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3916 visitor.SimulateInFramer(
3917 reinterpret_cast<const unsigned char*>(pad.c_str()),
3918 pad.length());
3920 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3921 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3922 visitor.framer_.error_code())
3923 << SpdyFramer::ErrorCodeToString(framer.error_code());
3924 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3927 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3928 SpdyFramer framer(spdy_version_);
3929 SpdySettingsIR settings_ir;
3930 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3931 SetFrameLength(control_frame.get(), 0, spdy_version_);
3932 TestSpdyVisitor visitor(spdy_version_);
3933 visitor.use_compression_ = false;
3934 visitor.SimulateInFramer(
3935 reinterpret_cast<unsigned char*>(control_frame->data()),
3936 framer.GetControlFrameHeaderSize());
3937 if (spdy_version_ <= SPDY3) {
3938 // Should generate an error, since zero-len settings frames are unsupported.
3939 EXPECT_EQ(1, visitor.error_count_);
3940 } else {
3941 // Zero-len settings frames are permitted as of HTTP/2.
3942 EXPECT_EQ(0, visitor.error_count_);
3946 // Tests handling of SETTINGS frames with invalid length.
3947 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3948 SpdyFramer framer(spdy_version_);
3949 SpdySettingsIR settings_ir;
3951 // Add a setting to pad the frame so that we don't get a buffer overflow when
3952 // calling SimulateInFramer() below.
3953 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3954 false,
3955 false,
3956 0x00000002);
3957 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3958 const size_t kNewLength = 14;
3959 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3960 TestSpdyVisitor visitor(spdy_version_);
3961 visitor.use_compression_ = false;
3962 visitor.SimulateInFramer(
3963 reinterpret_cast<unsigned char*>(control_frame->data()),
3964 framer.GetControlFrameHeaderSize() + kNewLength);
3965 // Should generate an error, since its not possible to have a
3966 // settings frame of length kNewLength.
3967 EXPECT_EQ(1, visitor.error_count_);
3970 // Tests handling of SETTINGS frames larger than the frame buffer size.
3971 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3972 SpdyFramer framer(spdy_version_);
3973 SpdySettingsIR settings_ir;
3974 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3975 false, // persist
3976 false, // persisted
3978 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3979 false, // persist
3980 false, // persisted
3982 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3983 false, // persist
3984 false, // persisted
3987 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3988 EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame->size());
3989 TestSpdyVisitor visitor(spdy_version_);
3990 visitor.use_compression_ = false;
3992 // Read all at once.
3993 visitor.SimulateInFramer(
3994 reinterpret_cast<unsigned char*>(control_frame->data()),
3995 control_frame->size());
3996 EXPECT_EQ(0, visitor.error_count_);
3997 EXPECT_EQ(3, visitor.setting_count_);
3998 if (spdy_version_ > SPDY3) {
3999 EXPECT_EQ(1, visitor.settings_ack_sent_);
4002 // Read data in small chunks.
4003 size_t framed_data = 0;
4004 size_t unframed_data = control_frame->size();
4005 size_t kReadChunkSize = 5; // Read five bytes at a time.
4006 while (unframed_data > 0) {
4007 size_t to_read = std::min(kReadChunkSize, unframed_data);
4008 visitor.SimulateInFramer(
4009 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
4010 to_read);
4011 unframed_data -= to_read;
4012 framed_data += to_read;
4014 EXPECT_EQ(0, visitor.error_count_);
4015 EXPECT_EQ(3 * 2, visitor.setting_count_);
4016 if (spdy_version_ > SPDY3) {
4017 EXPECT_EQ(2, visitor.settings_ack_sent_);
4021 // Tests handling of SETTINGS frame with duplicate entries.
4022 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
4023 SpdyFramer framer(spdy_version_);
4025 const unsigned char kV2FrameData[] = {
4026 0x80, spdy_version_ch_, 0x00, 0x04,
4027 0x00, 0x00, 0x00, 0x1C,
4028 0x00, 0x00, 0x00, 0x03,
4029 0x01, 0x00, 0x00, 0x00, // 1st Setting
4030 0x00, 0x00, 0x00, 0x02,
4031 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
4032 0x00, 0x00, 0x00, 0x03,
4033 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4034 0x00, 0x00, 0x00, 0x03,
4036 const unsigned char kV3FrameData[] = {
4037 0x80, spdy_version_ch_, 0x00, 0x04,
4038 0x00, 0x00, 0x00, 0x1C,
4039 0x00, 0x00, 0x00, 0x03,
4040 0x00, 0x00, 0x00, 0x01, // 1st Setting
4041 0x00, 0x00, 0x00, 0x02,
4042 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
4043 0x00, 0x00, 0x00, 0x03,
4044 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
4045 0x00, 0x00, 0x00, 0x03,
4047 const unsigned char kH2FrameData[] = {
4048 0x00, 0x00, 0x12, 0x04,
4049 0x00, 0x00, 0x00, 0x00,
4050 0x00, 0x00, 0x01, // 1st Setting
4051 0x00, 0x00, 0x00, 0x02,
4052 0x00, 0x01, // 2nd (duplicate) Setting
4053 0x00, 0x00, 0x00, 0x03,
4054 0x00, 0x03, // 3rd (unprocessed) Setting
4055 0x00, 0x00, 0x00, 0x03,
4058 TestSpdyVisitor visitor(spdy_version_);
4059 visitor.use_compression_ = false;
4060 if (IsSpdy2()) {
4061 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4062 } else if (IsSpdy3()) {
4063 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4064 } else {
4065 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4068 if (!IsHttp2()) {
4069 EXPECT_EQ(1, visitor.setting_count_);
4070 EXPECT_EQ(1, visitor.error_count_);
4071 } else {
4072 // In HTTP/2, duplicate settings are allowed;
4073 // each setting replaces the previous value for that setting.
4074 EXPECT_EQ(3, visitor.setting_count_);
4075 EXPECT_EQ(0, visitor.error_count_);
4076 EXPECT_EQ(1, visitor.settings_ack_sent_);
4080 // Tests handling of SETTINGS frame with a setting we don't recognize.
4081 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
4082 SpdyFramer framer(spdy_version_);
4084 const unsigned char kV2FrameData[] = {
4085 0x80, spdy_version_ch_, 0x00, 0x04,
4086 0x00, 0x00, 0x00, 0x1C,
4087 0x00, 0x00, 0x00, 0x01,
4088 0x10, 0x00, 0x00, 0x00, // 1st Setting
4089 0x00, 0x00, 0x00, 0x02,
4091 const unsigned char kV3FrameData[] = {
4092 0x80, spdy_version_ch_, 0x00, 0x04,
4093 0x00, 0x00, 0x00, 0x1C,
4094 0x00, 0x00, 0x00, 0x01,
4095 0x00, 0x00, 0x00, 0x10, // 1st Setting
4096 0x00, 0x00, 0x00, 0x02,
4098 const unsigned char kH2FrameData[] = {
4099 0x00, 0x00, 0x06, 0x04,
4100 0x00, 0x00, 0x00, 0x00,
4101 0x00, 0x00, 0x10, // 1st Setting
4102 0x00, 0x00, 0x00, 0x02,
4105 TestSpdyVisitor visitor(spdy_version_);
4106 visitor.use_compression_ = false;
4107 if (IsSpdy2()) {
4108 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4109 } else if (IsSpdy3()) {
4110 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4111 } else {
4112 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4115 if (!IsHttp2()) {
4116 EXPECT_EQ(0, visitor.setting_count_);
4117 EXPECT_EQ(1, visitor.error_count_);
4118 } else {
4119 // In HTTP/2, we ignore unknown settings because of extensions.
4120 EXPECT_EQ(0, visitor.setting_count_);
4121 EXPECT_EQ(0, visitor.error_count_);
4125 // Tests handling of SETTINGS frame with entries out of order.
4126 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
4127 SpdyFramer framer(spdy_version_);
4129 const unsigned char kV2FrameData[] = {
4130 0x80, spdy_version_ch_, 0x00, 0x04,
4131 0x00, 0x00, 0x00, 0x1C,
4132 0x00, 0x00, 0x00, 0x03,
4133 0x02, 0x00, 0x00, 0x00, // 1st Setting
4134 0x00, 0x00, 0x00, 0x02,
4135 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4136 0x00, 0x00, 0x00, 0x03,
4137 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4138 0x00, 0x00, 0x00, 0x03,
4140 const unsigned char kV3FrameData[] = {
4141 0x80, spdy_version_ch_, 0x00, 0x04,
4142 0x00, 0x00, 0x00, 0x1C,
4143 0x00, 0x00, 0x00, 0x03,
4144 0x00, 0x00, 0x00, 0x02, // 1st Setting
4145 0x00, 0x00, 0x00, 0x02,
4146 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4147 0x00, 0x00, 0x00, 0x03,
4148 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4149 0x00, 0x00, 0x00, 0x03,
4151 const unsigned char kH2FrameData[] = {
4152 0x00, 0x00, 0x12, 0x04,
4153 0x00, 0x00, 0x00, 0x00,
4154 0x00, 0x00, 0x02, // 1st Setting
4155 0x00, 0x00, 0x00, 0x02,
4156 0x00, 0x01, // 2nd (out of order) Setting
4157 0x00, 0x00, 0x00, 0x03,
4158 0x00, 0x03, // 3rd (unprocessed) Setting
4159 0x00, 0x00, 0x00, 0x03,
4162 TestSpdyVisitor visitor(spdy_version_);
4163 visitor.use_compression_ = false;
4164 if (IsSpdy2()) {
4165 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4166 } else if (IsSpdy3()) {
4167 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4168 } else {
4169 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4172 if (!IsHttp2()) {
4173 EXPECT_EQ(1, visitor.setting_count_);
4174 EXPECT_EQ(1, visitor.error_count_);
4175 } else {
4176 // In HTTP/2, settings are allowed in any order.
4177 EXPECT_EQ(3, visitor.setting_count_);
4178 EXPECT_EQ(0, visitor.error_count_);
4182 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4183 if (spdy_version_ <= SPDY3) {
4184 return;
4186 SpdyFramer framer(spdy_version_);
4188 const unsigned char kFrameData[] = {
4189 0x00, 0x00, 0x00, 0x04, 0x01,
4190 0x00, 0x00, 0x00, 0x00,
4193 TestSpdyVisitor visitor(spdy_version_);
4194 visitor.use_compression_ = false;
4195 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4197 EXPECT_EQ(0, visitor.error_count_);
4198 EXPECT_EQ(0, visitor.setting_count_);
4199 EXPECT_EQ(1, visitor.settings_ack_received_);
4202 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4203 if (spdy_version_ <= SPDY3) {
4204 return;
4207 const int kPaddingLen = 119;
4208 const char data_payload[] = "hello";
4210 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4211 SpdyFramer framer(spdy_version_);
4212 framer.set_visitor(&visitor);
4214 SpdyDataIR data_ir(1, data_payload);
4215 data_ir.set_padding_len(kPaddingLen);
4216 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4217 ASSERT_TRUE(frame.get() != NULL);
4219 int bytes_consumed = 0;
4221 // Send the frame header.
4222 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4223 kPaddingLen + strlen(data_payload),
4224 false));
4225 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4226 framer.ProcessInput(frame->data(),
4227 framer.GetDataFrameMinimumSize()));
4228 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4229 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4230 bytes_consumed += framer.GetDataFrameMinimumSize();
4232 // Send the padding length field.
4233 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
4234 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4235 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4236 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4237 bytes_consumed += 1;
4239 // Send the first two bytes of the data payload, i.e., "he".
4240 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4241 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4242 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4243 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4244 bytes_consumed += 2;
4246 // Send the rest three bytes of the data payload, i.e., "llo".
4247 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4248 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4249 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4250 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4251 bytes_consumed += 3;
4253 // Send the first 100 bytes of the padding payload.
4254 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
4255 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4256 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4257 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4258 bytes_consumed += 100;
4260 // Send rest of the padding payload.
4261 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
4262 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4263 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
4264 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4267 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4268 SpdyFramer framer(spdy_version_);
4269 scoped_ptr<SpdyFrame> control_frame(
4270 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4271 TestSpdyVisitor visitor(spdy_version_);
4272 visitor.SimulateInFramer(
4273 reinterpret_cast<unsigned char*>(control_frame->data()),
4274 control_frame->size());
4275 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4276 EXPECT_EQ(2, visitor.last_window_update_delta_);
4279 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4280 if (!IsSpdy3()) {
4281 return;
4283 SpdyFramer framer(spdy_version_);
4284 const unsigned char kV3FrameData[] = { // Also applies for V2.
4285 0x80, spdy_version_ch_, 0x00, 0x0A,
4286 0x00, 0x00, 0x00, 0x33,
4287 0x00, 0x03, 0x00, 0x00,
4288 0x00, 0x05, 'p', 'r',
4289 'o', 'o', 'f', 0x00,
4290 0x00, 0x00, 0x06, 'a',
4291 ' ', 'c', 'e', 'r',
4292 't', 0x00, 0x00, 0x00,
4293 0x0C, 'a', 'n', 'o',
4294 't', 'h', 'e', 'r',
4295 ' ', 'c', 'e', 'r',
4296 't', 0x00, 0x00, 0x00,
4297 0x0A, 'f', 'i', 'n',
4298 'a', 'l', ' ', 'c',
4299 'e', 'r', 't',
4301 TestSpdyVisitor visitor(spdy_version_);
4302 visitor.use_compression_ = false;
4303 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4304 EXPECT_EQ(0, visitor.error_count_);
4307 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4308 if (!IsSpdy3()) {
4309 return;
4311 SpdyFramer framer(spdy_version_);
4312 const unsigned char kV3FrameData[] = { // Also applies for V2.
4313 0x80, spdy_version_ch_, 0x00, 0x0A,
4314 0x00, 0x00, 0x00, 0x33,
4315 0x00, 0x03, 0x00, 0x00,
4316 0x00, 0x05, 'p', 'r',
4317 'o', 'o', 'f', 0x00,
4318 0x00, 0x00, 0x06, 'a',
4319 ' ', 'c', 'e', 'r',
4320 't', 0x00, 0x00, 0x00,
4321 0x0C, 'a', 'n', 'o',
4322 't', 'h', 'e', 'r',
4323 ' ', 'c', 'e', 'r',
4324 't', 0x00, 0x00, 0x00,
4325 0x0A, 'f', 'i', 'n',
4326 'a', 'l', ' ', 'c',
4327 'e', 'r', 't',
4329 TestSpdyVisitor visitor(spdy_version_);
4330 visitor.use_compression_ = false;
4331 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4332 arraysize(kV3FrameData));
4333 scoped_ptr<SpdyFrame> control_frame(
4334 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4335 multiple_frame_data.append(string(control_frame->data(),
4336 control_frame->size()));
4337 visitor.SimulateInFramer(
4338 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4339 multiple_frame_data.length());
4340 EXPECT_EQ(0, visitor.error_count_);
4341 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4342 EXPECT_EQ(2, visitor.last_window_update_delta_);
4345 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4346 if (spdy_version_ <= SPDY3) {
4347 return;
4350 SpdyFramer framer(spdy_version_);
4351 SpdyPushPromiseIR push_promise(42, 57);
4352 push_promise.SetHeader("foo", "bar");
4353 push_promise.SetHeader("bar", "foofoo");
4354 SpdyHeaderBlock headers = push_promise.name_value_block();
4355 scoped_ptr<SpdySerializedFrame> frame(
4356 framer.SerializePushPromise(push_promise));
4357 EXPECT_TRUE(frame.get() != NULL);
4358 TestSpdyVisitor visitor(spdy_version_);
4359 visitor.use_compression_ = true;
4360 visitor.SimulateInFramer(
4361 reinterpret_cast<unsigned char*>(frame->data()),
4362 frame->size());
4363 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4364 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4365 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4368 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4369 if (spdy_version_ <= SPDY3) {
4370 return;
4373 const unsigned char kInput[] = {
4374 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4375 0x00, 0x00, 0x00, 0x01, // Stream 1
4376 0x03, // Padding of 3.
4377 0x00, 0x06, 0x63, 0x6f,
4378 0x6f, 0x6b, 0x69, 0x65,
4379 0x07, 0x66, 0x6f, 0x6f,
4380 0x3d, 0x62, 0x61, 0x72,
4381 0x00, 0x00, 0x00,
4383 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4384 0x00, 0x00, 0x00, 0x01, // Stream 1
4385 0x00, 0x06, 0x63, 0x6f,
4386 0x6f, 0x6b, 0x69, 0x65,
4387 0x08, 0x62, 0x61, 0x7a,
4388 0x3d, 0x62, 0x69, 0x6e,
4389 0x67, 0x00, 0x06, 0x63,
4391 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4392 0x00, 0x00, 0x00, 0x01, // Stream 1
4393 0x6f, 0x6f, 0x6b, 0x69,
4394 0x65, 0x00, 0x00, 0x04,
4395 0x6e, 0x61, 0x6d, 0x65,
4396 0x05, 0x76, 0x61, 0x6c,
4397 0x75, 0x65,
4400 TestSpdyVisitor visitor(spdy_version_);
4401 visitor.SimulateInFramer(kInput, sizeof(kInput));
4403 EXPECT_EQ(0, visitor.error_count_);
4404 EXPECT_EQ(1, visitor.headers_frame_count_);
4405 EXPECT_EQ(2, visitor.continuation_count_);
4406 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4407 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4409 EXPECT_THAT(visitor.headers_,
4410 testing::ElementsAre(
4411 testing::Pair("cookie", "foo=bar; baz=bing; "),
4412 testing::Pair("name", "value")));
4415 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4416 if (spdy_version_ <= SPDY3) {
4417 return;
4420 const unsigned char kInput[] = {
4421 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4422 0x00, 0x00, 0x00, 0x01, // Stream 1
4423 0x00, 0x06, 0x63, 0x6f,
4424 0x6f, 0x6b, 0x69, 0x65,
4425 0x07, 0x66, 0x6f, 0x6f,
4426 0x3d, 0x62, 0x61, 0x72,
4428 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4429 0x00, 0x00, 0x00, 0x01, // Stream 1
4430 0x00, 0x06, 0x63, 0x6f,
4431 0x6f, 0x6b, 0x69, 0x65,
4432 0x08, 0x62, 0x61, 0x7a,
4433 0x3d, 0x62, 0x69, 0x6e,
4434 0x67, 0x00, 0x06, 0x63,
4436 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4437 0x00, 0x00, 0x00, 0x01, // Stream 1
4438 0x6f, 0x6f, 0x6b, 0x69,
4439 0x65, 0x00, 0x00, 0x04,
4440 0x6e, 0x61, 0x6d, 0x65,
4441 0x05, 0x76, 0x61, 0x6c,
4442 0x75, 0x65,
4445 SpdyFramer framer(spdy_version_);
4446 TestSpdyVisitor visitor(spdy_version_);
4447 visitor.SimulateInFramer(kInput, sizeof(kInput));
4449 EXPECT_EQ(0, visitor.error_count_);
4450 EXPECT_EQ(1, visitor.headers_frame_count_);
4451 EXPECT_EQ(2, visitor.continuation_count_);
4452 EXPECT_EQ(1, visitor.fin_flag_count_);
4453 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4454 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4456 EXPECT_THAT(visitor.headers_,
4457 testing::ElementsAre(
4458 testing::Pair("cookie", "foo=bar; baz=bing; "),
4459 testing::Pair("name", "value")));
4462 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4463 if (spdy_version_ <= SPDY3) {
4464 return;
4467 const unsigned char kInput[] = {
4468 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4469 0x08, 0x00, 0x00, 0x00, // PADDED
4470 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4471 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4472 0x63, 0x6f, 0x6f, 0x6b,
4473 0x69, 0x65, 0x07, 0x66,
4474 0x6f, 0x6f, 0x3d, 0x62,
4475 0x61, 0x72, 0x00, 0x00,
4477 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4478 0x00, 0x00, 0x00, 0x00,
4479 0x01, 0x00, 0x06, 0x63, // Stream 1
4480 0x6f, 0x6f, 0x6b, 0x69,
4481 0x65, 0x08, 0x62, 0x61,
4482 0x7a, 0x3d, 0x62, 0x69,
4483 0x6e, 0x67, 0x00, 0x06,
4484 0x63,
4486 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4487 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4488 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4489 0x69, 0x65, 0x00, 0x00,
4490 0x04, 0x6e, 0x61, 0x6d,
4491 0x65, 0x05, 0x76, 0x61,
4492 0x6c, 0x75, 0x65,
4495 SpdyFramer framer(spdy_version_);
4496 TestSpdyVisitor visitor(spdy_version_);
4497 visitor.SimulateInFramer(kInput, sizeof(kInput));
4499 EXPECT_EQ(0, visitor.error_count_);
4500 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4501 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4502 EXPECT_EQ(2, visitor.continuation_count_);
4503 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4504 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4506 EXPECT_THAT(visitor.headers_,
4507 testing::ElementsAre(
4508 testing::Pair("cookie", "foo=bar; baz=bing; "),
4509 testing::Pair("name", "value")));
4512 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4513 if (spdy_version_ <= SPDY3) {
4514 return;
4517 const unsigned char kInput[] = {
4518 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4519 0x00, 0x00, 0x00, 0x01, // Stream 1
4520 0x00, 0x06, 0x63, 0x6f,
4521 0x6f, 0x6b, 0x69, 0x65,
4522 0x07, 0x66, 0x6f, 0x6f,
4523 0x3d, 0x62, 0x61, 0x72,
4525 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4526 0x00, 0x00, 0x00, 0x02, // Stream 2
4527 0x00, 0x06, 0x63, 0x6f,
4528 0x6f, 0x6b, 0x69, 0x65,
4529 0x08, 0x62, 0x61, 0x7a,
4530 0x3d, 0x62, 0x69, 0x6e,
4531 0x67, 0x00, 0x06, 0x63,
4534 SpdyFramer framer(spdy_version_);
4535 TestSpdyVisitor visitor(spdy_version_);
4536 framer.set_visitor(&visitor);
4537 visitor.SimulateInFramer(kInput, sizeof(kInput));
4539 EXPECT_EQ(1, visitor.error_count_);
4540 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4541 visitor.framer_.error_code())
4542 << SpdyFramer::ErrorCodeToString(framer.error_code());
4543 EXPECT_EQ(1, visitor.headers_frame_count_);
4544 EXPECT_EQ(0, visitor.continuation_count_);
4545 EXPECT_EQ(0u, visitor.header_buffer_length_);
4548 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4549 if (spdy_version_ <= SPDY3) {
4550 return;
4553 const unsigned char kInput[] = {
4554 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4555 0x00, 0x00, 0x00, 0x01, // Stream 1
4556 0x00, 0x06, 0x63, 0x6f,
4557 0x6f, 0x6b, 0x69, 0x65,
4558 0x07, 0x66, 0x6f, 0x6f,
4559 0x3d, 0x62, 0x61, 0x72,
4562 SpdyFramer framer(spdy_version_);
4563 TestSpdyVisitor visitor(spdy_version_);
4564 framer.set_visitor(&visitor);
4565 visitor.SimulateInFramer(kInput, sizeof(kInput));
4567 EXPECT_EQ(1, visitor.error_count_);
4568 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4569 visitor.framer_.error_code())
4570 << SpdyFramer::ErrorCodeToString(framer.error_code());
4571 EXPECT_EQ(0, visitor.continuation_count_);
4572 EXPECT_EQ(0u, visitor.header_buffer_length_);
4575 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4576 if (spdy_version_ <= SPDY3) {
4577 return;
4580 const unsigned char kInput[] = {
4581 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4582 0x00, 0x00, 0x00, 0x01, // Stream 1
4583 0x00, 0x06, 0x63, 0x6f,
4584 0x6f, 0x6b, 0x69, 0x65,
4585 0x07, 0x66, 0x6f, 0x6f,
4586 0x3d, 0x62, 0x61, 0x72,
4588 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4589 0x00, 0x00, 0x00, 0x04,
4590 0xde, 0xad, 0xbe, 0xef,
4593 SpdyFramer framer(spdy_version_);
4594 TestSpdyVisitor visitor(spdy_version_);
4595 framer.set_visitor(&visitor);
4596 visitor.SimulateInFramer(kInput, sizeof(kInput));
4598 EXPECT_EQ(1, visitor.error_count_);
4599 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4600 visitor.framer_.error_code())
4601 << SpdyFramer::ErrorCodeToString(framer.error_code());
4602 EXPECT_EQ(1, visitor.headers_frame_count_);
4603 EXPECT_EQ(0, visitor.continuation_count_);
4604 EXPECT_EQ(0u, visitor.header_buffer_length_);
4605 EXPECT_EQ(0, visitor.data_frame_count_);
4608 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4609 if (spdy_version_ <= SPDY3) {
4610 return;
4613 const unsigned char kInput[] = {
4614 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4615 0x00, 0x00, 0x00, 0x01, // Stream 1
4616 0x00, 0x06, 0x63, 0x6f,
4617 0x6f, 0x6b, 0x69, 0x65,
4618 0x07, 0x66, 0x6f, 0x6f,
4619 0x3d, 0x62, 0x61, 0x72,
4621 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4622 0x00, 0x00, 0x00, 0x01, // Stream 1
4623 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4624 0x6f, 0x6b, 0x69, 0x65,
4625 0x08, 0x62, 0x61, 0x7a,
4626 0x3d, 0x62, 0x69, 0x6e,
4627 0x67, 0x00, 0x06, 0x63,
4630 SpdyFramer framer(spdy_version_);
4631 TestSpdyVisitor visitor(spdy_version_);
4632 framer.set_visitor(&visitor);
4633 visitor.SimulateInFramer(kInput, sizeof(kInput));
4635 EXPECT_EQ(1, visitor.error_count_);
4636 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4637 visitor.framer_.error_code())
4638 << SpdyFramer::ErrorCodeToString(framer.error_code());
4639 EXPECT_EQ(1, visitor.headers_frame_count_);
4640 EXPECT_EQ(0, visitor.continuation_count_);
4641 EXPECT_EQ(0u, visitor.header_buffer_length_);
4642 EXPECT_EQ(0, visitor.data_frame_count_);
4645 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4646 if (spdy_version_ <= SPDY3) {
4647 return;
4649 const unsigned char kInput[] = {
4650 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4651 0x00, 0x00, 0x00, 0x01, // Stream 1
4652 0xde, 0xad, 0xbe, 0xef,
4653 0xde, 0xad, 0xbe, 0xef,
4654 0xde, 0xad, 0xbe, 0xef,
4657 TestSpdyVisitor visitor(spdy_version_);
4658 visitor.SimulateInFramer(kInput, sizeof(kInput));
4660 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4661 EXPECT_EQ(0, visitor.error_count_);
4662 EXPECT_EQ(12, visitor.data_bytes_);
4663 EXPECT_EQ(0, visitor.fin_frame_count_);
4664 EXPECT_EQ(0, visitor.fin_flag_count_);
4667 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4668 if (spdy_version_ <= SPDY3) {
4669 return;
4671 const unsigned char kInput[] = {
4672 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4673 0x00, 0x00, 0x00, 0x01, // Stream 1
4674 0x00, 0x06, 0x63, 0x6f,
4675 0x6f, 0x6b, 0x69, 0x65,
4676 0x07, 0x66, 0x6f, 0x6f,
4677 0x3d, 0x62, 0x61, 0x72,
4680 TestSpdyVisitor visitor(spdy_version_);
4681 visitor.SimulateInFramer(kInput, sizeof(kInput));
4683 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4684 EXPECT_EQ(0, visitor.error_count_);
4685 EXPECT_EQ(1, visitor.headers_frame_count_);
4686 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4688 EXPECT_THAT(visitor.headers_,
4689 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4692 TEST_P(SpdyFramerTest, ReadGarbage) {
4693 SpdyFramer framer(spdy_version_);
4694 unsigned char garbage_frame[256];
4695 memset(garbage_frame, ~0, sizeof(garbage_frame));
4696 TestSpdyVisitor visitor(spdy_version_);
4697 visitor.use_compression_ = false;
4698 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4699 EXPECT_EQ(1, visitor.error_count_);
4702 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4703 if (spdy_version_ <= SPDY3) {
4704 return;
4706 SpdyFramer framer(spdy_version_);
4708 // The unrecognized frame type should still have a valid length.
4709 const unsigned char unknown_frame[] = {
4710 0x00, 0x00, 0x08, 0xff, 0xff,
4711 0xff, 0xff, 0xff, 0xff,
4712 0xff, 0xff, 0xff, 0xff,
4713 0xff, 0xff, 0xff, 0xff,
4715 TestSpdyVisitor visitor(spdy_version_);
4717 // Simulate the case where the stream id validation checks out.
4718 visitor.on_unknown_frame_result_ = true;
4719 visitor.use_compression_ = false;
4720 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4721 EXPECT_EQ(0, visitor.error_count_);
4723 // Follow it up with a valid control frame to make sure we handle
4724 // subsequent frames correctly.
4725 SpdySettingsIR settings_ir;
4726 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4727 false, // persist
4728 false, // persisted
4729 10);
4730 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4731 visitor.SimulateInFramer(
4732 reinterpret_cast<unsigned char*>(control_frame->data()),
4733 control_frame->size());
4734 EXPECT_EQ(0, visitor.error_count_);
4735 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4736 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4739 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4740 if (!IsHttp2()) {
4741 return;
4743 SpdyFramer framer(spdy_version_);
4744 const unsigned char kFrameData[] = {
4745 0x00, 0x00, 0x08, 0xff, 0xff,
4746 0xff, 0xff, 0xff, 0xff,
4747 0xff, 0xff, 0xff, 0xff,
4748 0xff, 0xff, 0xff, 0xff,
4750 TestSpdyVisitor visitor(spdy_version_);
4751 visitor.use_compression_ = false;
4752 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4753 EXPECT_EQ(1, visitor.error_count_);
4756 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4757 if (IsHttp2()) {
4758 // Not valid for HTTP/2 since there is no version field.
4759 return;
4761 SpdyFramer framer(spdy_version_);
4762 const unsigned char kFrameData[] = {
4763 0x80, spdy_version_ch_, 0xff, 0xff,
4764 0xff, 0xff, 0xff, 0xff,
4766 TestSpdyVisitor visitor(spdy_version_);
4767 visitor.use_compression_ = false;
4768 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4769 EXPECT_EQ(1, visitor.error_count_);
4772 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4773 if (spdy_version_ <= SPDY3) {
4774 return;
4776 const unsigned char kInput[] = {
4777 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4778 0x00, 0x00, 0x00, 0x01, // Stream 1
4779 0xef, 0xef, 0xff, 0xff,
4780 0xff, 0xff, 0xff, 0xff,
4781 0xff, 0xff, 0xff, 0xff,
4782 0xff, 0xff, 0xff, 0xff,
4783 0xff, 0xff,
4786 TestSpdyVisitor visitor(spdy_version_);
4787 visitor.SimulateInFramer(kInput, arraysize(kInput));
4788 EXPECT_EQ(1, visitor.error_count_);
4791 TEST_P(SpdyFramerTest, SizesTest) {
4792 SpdyFramer framer(spdy_version_);
4793 if (IsHttp2()) {
4794 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4795 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4796 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4797 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4798 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4799 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4800 EXPECT_EQ(17u, framer.GetPingSize());
4801 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4802 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4803 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4804 EXPECT_EQ(9u, framer.GetBlockedSize());
4805 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4806 EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
4807 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4808 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4809 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4810 } else {
4811 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4812 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4813 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4814 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4815 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4816 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4817 EXPECT_EQ(12u, framer.GetPingSize());
4818 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4819 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4820 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4821 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4822 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4823 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4827 TEST_P(SpdyFramerTest, StateToStringTest) {
4828 EXPECT_STREQ("ERROR",
4829 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4830 EXPECT_STREQ("AUTO_RESET",
4831 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4832 EXPECT_STREQ("RESET",
4833 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4834 EXPECT_STREQ("READING_COMMON_HEADER",
4835 SpdyFramer::StateToString(
4836 SpdyFramer::SPDY_READING_COMMON_HEADER));
4837 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4838 SpdyFramer::StateToString(
4839 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4840 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4841 SpdyFramer::StateToString(
4842 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4843 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4844 SpdyFramer::StateToString(
4845 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4846 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4847 SpdyFramer::StateToString(
4848 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4849 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4850 SpdyFramer::StateToString(
4851 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4852 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4853 SpdyFramer::StateToString(
4854 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4855 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4856 SpdyFramer::StateToString(
4857 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4858 EXPECT_STREQ("UNKNOWN_STATE",
4859 SpdyFramer::StateToString(
4860 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4863 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4864 EXPECT_STREQ("NO_ERROR",
4865 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4866 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4867 SpdyFramer::ErrorCodeToString(
4868 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4869 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4870 SpdyFramer::ErrorCodeToString(
4871 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4872 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4873 SpdyFramer::ErrorCodeToString(
4874 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4875 EXPECT_STREQ("UNSUPPORTED_VERSION",
4876 SpdyFramer::ErrorCodeToString(
4877 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4878 EXPECT_STREQ("DECOMPRESS_FAILURE",
4879 SpdyFramer::ErrorCodeToString(
4880 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4881 EXPECT_STREQ("COMPRESS_FAILURE",
4882 SpdyFramer::ErrorCodeToString(
4883 SpdyFramer::SPDY_COMPRESS_FAILURE));
4884 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4885 SpdyFramer::ErrorCodeToString(
4886 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4887 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4888 SpdyFramer::ErrorCodeToString(
4889 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4890 EXPECT_STREQ("UNKNOWN_ERROR",
4891 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4894 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4895 EXPECT_STREQ("INVALID",
4896 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4897 EXPECT_STREQ("PROTOCOL_ERROR",
4898 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4899 EXPECT_STREQ("INVALID_STREAM",
4900 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4901 EXPECT_STREQ("REFUSED_STREAM",
4902 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4903 EXPECT_STREQ("UNSUPPORTED_VERSION",
4904 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4905 EXPECT_STREQ("CANCEL",
4906 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4907 EXPECT_STREQ("INTERNAL_ERROR",
4908 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4909 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4910 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4911 EXPECT_STREQ("UNKNOWN_STATUS",
4912 SpdyFramer::StatusCodeToString(-1));
4915 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4916 EXPECT_STREQ("DATA",
4917 SpdyFramer::FrameTypeToString(DATA));
4918 EXPECT_STREQ("SYN_STREAM",
4919 SpdyFramer::FrameTypeToString(SYN_STREAM));
4920 EXPECT_STREQ("SYN_REPLY",
4921 SpdyFramer::FrameTypeToString(SYN_REPLY));
4922 EXPECT_STREQ("RST_STREAM",
4923 SpdyFramer::FrameTypeToString(RST_STREAM));
4924 EXPECT_STREQ("SETTINGS",
4925 SpdyFramer::FrameTypeToString(SETTINGS));
4926 EXPECT_STREQ("PING",
4927 SpdyFramer::FrameTypeToString(PING));
4928 EXPECT_STREQ("GOAWAY",
4929 SpdyFramer::FrameTypeToString(GOAWAY));
4930 EXPECT_STREQ("HEADERS",
4931 SpdyFramer::FrameTypeToString(HEADERS));
4932 EXPECT_STREQ("WINDOW_UPDATE",
4933 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4934 EXPECT_STREQ("PUSH_PROMISE",
4935 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4936 EXPECT_STREQ("CREDENTIAL",
4937 SpdyFramer::FrameTypeToString(CREDENTIAL));
4938 EXPECT_STREQ("CONTINUATION",
4939 SpdyFramer::FrameTypeToString(CONTINUATION));
4942 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4943 if (IsHttp2()) {
4944 // TODO(hkhalil): catch probable HTTP response in HTTP/2?
4945 return;
4948 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4949 SpdyFramer framer(spdy_version_);
4950 framer.set_visitor(&visitor);
4952 EXPECT_CALL(visitor, OnError(_));
4953 framer.ProcessInput("HTTP/1.1", 8);
4954 EXPECT_TRUE(framer.probable_http_response());
4955 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4956 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4957 << SpdyFramer::ErrorCodeToString(framer.error_code());
4960 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4961 SpdyFramer framer(spdy_version_);
4962 framer.set_visitor(&visitor);
4964 EXPECT_CALL(visitor, OnError(_));
4965 framer.ProcessInput("HTTP/1.0", 8);
4966 EXPECT_TRUE(framer.probable_http_response());
4967 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4968 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4969 << SpdyFramer::ErrorCodeToString(framer.error_code());
4973 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4974 if (spdy_version_ > SPDY3) {
4975 return;
4978 uint8 flags = 0;
4979 do {
4980 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4982 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4983 SpdyFramer framer(spdy_version_);
4984 framer.set_visitor(&visitor);
4986 SpdyDataIR data_ir(1, "hello");
4987 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4988 SetFrameFlags(frame.get(), flags, spdy_version_);
4990 if (flags & ~DATA_FLAG_FIN) {
4991 EXPECT_CALL(visitor, OnError(_));
4992 } else {
4993 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4994 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4995 if (flags & DATA_FLAG_FIN) {
4996 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5000 framer.ProcessInput(frame->data(), frame->size());
5001 if (flags & ~DATA_FLAG_FIN) {
5002 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5003 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
5004 framer.error_code())
5005 << SpdyFramer::ErrorCodeToString(framer.error_code());
5006 } else {
5007 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5008 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5009 << SpdyFramer::ErrorCodeToString(framer.error_code());
5011 } while (++flags != 0);
5014 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
5015 if (spdy_version_ <= SPDY3) {
5016 return;
5019 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
5020 DATA_FLAG_PADDED;
5022 uint8 flags = 0;
5023 do {
5024 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5026 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5027 SpdyFramer framer(spdy_version_);
5028 framer.set_visitor(&visitor);
5030 SpdyDataIR data_ir(1, "hello");
5031 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
5032 SetFrameFlags(frame.get(), flags, spdy_version_);
5034 if (flags & ~valid_data_flags) {
5035 EXPECT_CALL(visitor, OnError(_));
5036 } else {
5037 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
5038 if (flags & DATA_FLAG_PADDED) {
5039 // The first byte of payload is parsed as padding length.
5040 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
5041 // Expect Error since the frame ends prematurely.
5042 EXPECT_CALL(visitor, OnError(_));
5043 } else {
5044 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
5045 if (flags & DATA_FLAG_FIN) {
5046 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5051 framer.ProcessInput(frame->data(), frame->size());
5052 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
5053 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5054 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
5055 << SpdyFramer::ErrorCodeToString(framer.error_code());
5056 } else {
5057 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5058 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5059 << SpdyFramer::ErrorCodeToString(framer.error_code());
5061 } while (++flags != 0);
5064 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
5065 if (!IsSpdy2() && !IsSpdy3()) {
5066 // SYN_STREAM not supported in SPDY>3
5067 return;
5069 uint8 flags = 0;
5070 do {
5071 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5073 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5074 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5075 SpdyFramer framer(spdy_version_);
5076 framer.set_visitor(&visitor);
5077 framer.set_debug_visitor(&debug_visitor);
5079 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
5081 SpdySynStreamIR syn_stream(8);
5082 syn_stream.set_associated_to_stream_id(3);
5083 syn_stream.set_priority(1);
5084 syn_stream.SetHeader("foo", "bar");
5085 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5086 SetFrameFlags(frame.get(), flags, spdy_version_);
5088 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5089 EXPECT_CALL(visitor, OnError(_));
5090 } else {
5091 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
5092 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
5093 flags & CONTROL_FLAG_UNIDIRECTIONAL));
5094 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
5095 .WillRepeatedly(testing::Return(true));
5096 if (flags & DATA_FLAG_FIN) {
5097 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5098 } else {
5099 // Do not close the stream if we are expecting a CONTINUATION frame.
5100 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5104 framer.ProcessInput(frame->data(), frame->size());
5105 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5106 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5107 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5108 framer.error_code())
5109 << SpdyFramer::ErrorCodeToString(framer.error_code());
5110 } else {
5111 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5112 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5113 << SpdyFramer::ErrorCodeToString(framer.error_code());
5115 } while (++flags != 0);
5118 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
5119 if (!IsSpdy2() && !IsSpdy3()) {
5120 // SYN_REPLY not supported in SPDY>3
5121 return;
5123 uint8 flags = 0;
5124 do {
5125 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5127 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5128 SpdyFramer framer(spdy_version_);
5129 framer.set_visitor(&visitor);
5131 SpdySynReplyIR syn_reply(37);
5132 syn_reply.SetHeader("foo", "bar");
5133 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5134 SetFrameFlags(frame.get(), flags, spdy_version_);
5136 if (flags & ~CONTROL_FLAG_FIN) {
5137 EXPECT_CALL(visitor, OnError(_));
5138 } else {
5139 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5140 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5141 .WillRepeatedly(testing::Return(true));
5142 if (flags & DATA_FLAG_FIN) {
5143 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5147 framer.ProcessInput(frame->data(), frame->size());
5148 if (flags & ~CONTROL_FLAG_FIN) {
5149 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5150 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5151 framer.error_code())
5152 << SpdyFramer::ErrorCodeToString(framer.error_code());
5153 } else {
5154 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5155 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5156 << SpdyFramer::ErrorCodeToString(framer.error_code());
5158 } while (++flags != 0);
5161 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5162 uint8 flags = 0;
5163 do {
5164 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5166 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5167 SpdyFramer framer(spdy_version_);
5168 framer.set_visitor(&visitor);
5170 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5171 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5172 SetFrameFlags(frame.get(), flags, spdy_version_);
5174 if (flags != 0) {
5175 EXPECT_CALL(visitor, OnError(_));
5176 } else {
5177 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5180 framer.ProcessInput(frame->data(), frame->size());
5181 if (flags != 0) {
5182 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5183 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5184 framer.error_code())
5185 << SpdyFramer::ErrorCodeToString(framer.error_code());
5186 } else {
5187 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5188 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5189 << SpdyFramer::ErrorCodeToString(framer.error_code());
5191 } while (++flags != 0);
5194 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5195 if (spdy_version_ > SPDY3) { return; }
5196 uint8 flags = 0;
5197 do {
5198 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5200 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5201 SpdyFramer framer(spdy_version_);
5202 framer.set_visitor(&visitor);
5204 SpdySettingsIR settings_ir;
5205 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5206 false,
5207 false,
5208 54321);
5209 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5210 SetFrameFlags(frame.get(), flags, spdy_version_);
5212 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5213 EXPECT_CALL(visitor, OnError(_));
5214 } else {
5215 EXPECT_CALL(visitor, OnSettings(
5216 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5217 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5218 SETTINGS_FLAG_NONE, 54321));
5219 EXPECT_CALL(visitor, OnSettingsEnd());
5222 framer.ProcessInput(frame->data(), frame->size());
5223 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5224 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5225 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5226 framer.error_code())
5227 << SpdyFramer::ErrorCodeToString(framer.error_code());
5228 } else {
5229 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5230 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5231 << SpdyFramer::ErrorCodeToString(framer.error_code());
5233 } while (++flags != 0);
5236 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5237 if (spdy_version_ <= SPDY3) { return; }
5238 uint8 flags = 0;
5239 do {
5240 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5242 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5243 SpdyFramer framer(spdy_version_);
5244 framer.set_visitor(&visitor);
5246 SpdySettingsIR settings_ir;
5247 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5248 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5249 SetFrameFlags(frame.get(), flags, spdy_version_);
5251 if (flags != 0) {
5252 EXPECT_CALL(visitor, OnError(_));
5253 } else {
5254 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5255 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5256 EXPECT_CALL(visitor, OnSettingsEnd());
5259 framer.ProcessInput(frame->data(), frame->size());
5260 if (flags & ~SETTINGS_FLAG_ACK) {
5261 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5262 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5263 framer.error_code())
5264 << SpdyFramer::ErrorCodeToString(framer.error_code());
5265 } else if (flags & SETTINGS_FLAG_ACK) {
5266 // The frame is invalid because ACK frames should have no payload.
5267 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5268 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5269 framer.error_code())
5270 << SpdyFramer::ErrorCodeToString(framer.error_code());
5271 } else {
5272 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5273 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5274 << SpdyFramer::ErrorCodeToString(framer.error_code());
5276 } while (++flags != 0);
5279 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5280 uint8 flags = 0;
5281 do {
5282 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5284 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5285 SpdyFramer framer(spdy_version_);
5286 framer.set_visitor(&visitor);
5288 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5289 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5290 SetFrameFlags(frame.get(), flags, spdy_version_);
5292 if (flags != 0) {
5293 EXPECT_CALL(visitor, OnError(_));
5294 } else {
5295 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5298 framer.ProcessInput(frame->data(), frame->size());
5299 if (flags != 0) {
5300 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5301 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5302 framer.error_code())
5303 << SpdyFramer::ErrorCodeToString(framer.error_code());
5304 } else {
5305 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5306 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5307 << SpdyFramer::ErrorCodeToString(framer.error_code());
5309 } while (++flags != 0);
5312 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5313 uint8 flags = 0;
5314 do {
5315 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5317 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5318 SpdyFramer framer(spdy_version_);
5319 framer.set_visitor(&visitor);
5321 SpdyHeadersIR headers_ir(57);
5322 if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) {
5323 headers_ir.set_priority(3);
5324 headers_ir.set_has_priority(true);
5325 headers_ir.set_parent_stream_id(5);
5326 headers_ir.set_exclusive(true);
5328 headers_ir.SetHeader("foo", "bar");
5329 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5330 uint8 set_flags = flags;
5331 if (IsHttp2()) {
5332 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5333 // and implement framing.
5334 set_flags &= ~HEADERS_FLAG_PADDED;
5336 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5338 if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
5339 EXPECT_CALL(visitor, OnError(_));
5340 } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
5341 HEADERS_FLAG_END_HEADERS |
5342 HEADERS_FLAG_END_SEGMENT |
5343 HEADERS_FLAG_PADDED |
5344 HEADERS_FLAG_PRIORITY)) {
5345 EXPECT_CALL(visitor, OnError(_));
5346 } else {
5347 // Expected callback values
5348 SpdyStreamId stream_id = 57;
5349 bool has_priority = false;
5350 SpdyPriority priority = 0;
5351 SpdyStreamId parent_stream_id = 0;
5352 bool exclusive = false;
5353 bool fin = flags & CONTROL_FLAG_FIN;
5354 bool end = !IsHttp2() || (flags & HEADERS_FLAG_END_HEADERS);
5355 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5356 has_priority = true;
5357 priority = 3;
5358 parent_stream_id = 5;
5359 exclusive = true;
5361 EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority,
5362 parent_stream_id, exclusive, fin, end));
5363 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5364 .WillRepeatedly(testing::Return(true));
5365 if (flags & DATA_FLAG_FIN &&
5366 (!IsHttp2() || flags & HEADERS_FLAG_END_HEADERS)) {
5367 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5368 } else {
5369 // Do not close the stream if we are expecting a CONTINUATION frame.
5370 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5374 framer.ProcessInput(frame->data(), frame->size());
5375 if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
5376 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5377 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5378 framer.error_code())
5379 << SpdyFramer::ErrorCodeToString(framer.error_code());
5380 } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
5381 HEADERS_FLAG_END_HEADERS |
5382 HEADERS_FLAG_END_SEGMENT |
5383 HEADERS_FLAG_PADDED |
5384 HEADERS_FLAG_PRIORITY)) {
5385 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5386 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5387 framer.error_code())
5388 << SpdyFramer::ErrorCodeToString(framer.error_code());
5389 } else if (IsHttp2() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5390 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5391 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5392 << SpdyFramer::ErrorCodeToString(framer.error_code());
5393 } else {
5394 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5395 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5396 << SpdyFramer::ErrorCodeToString(framer.error_code());
5398 } while (++flags != 0);
5401 TEST_P(SpdyFramerTest, PingFrameFlags) {
5402 uint8 flags = 0;
5403 do {
5404 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5406 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5407 SpdyFramer framer(spdy_version_);
5408 framer.set_visitor(&visitor);
5410 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5411 SetFrameFlags(frame.get(), flags, spdy_version_);
5413 if (spdy_version_ > SPDY3 &&
5414 flags == PING_FLAG_ACK) {
5415 EXPECT_CALL(visitor, OnPing(42, true));
5416 } else if (flags == 0) {
5417 EXPECT_CALL(visitor, OnPing(42, false));
5418 } else {
5419 EXPECT_CALL(visitor, OnError(_));
5422 framer.ProcessInput(frame->data(), frame->size());
5423 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5424 flags == 0) {
5425 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5426 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5427 << SpdyFramer::ErrorCodeToString(framer.error_code());
5428 } else {
5429 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5430 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5431 framer.error_code())
5432 << SpdyFramer::ErrorCodeToString(framer.error_code());
5434 } while (++flags != 0);
5437 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5438 uint8 flags = 0;
5439 do {
5440 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5442 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5443 SpdyFramer framer(spdy_version_);
5444 framer.set_visitor(&visitor);
5446 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5447 SpdyWindowUpdateIR(4, 1024)));
5448 SetFrameFlags(frame.get(), flags, spdy_version_);
5450 if (flags != 0) {
5451 EXPECT_CALL(visitor, OnError(_));
5452 } else {
5453 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5456 framer.ProcessInput(frame->data(), frame->size());
5457 if (flags != 0) {
5458 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5459 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5460 framer.error_code())
5461 << SpdyFramer::ErrorCodeToString(framer.error_code());
5462 } else {
5463 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5464 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5465 << SpdyFramer::ErrorCodeToString(framer.error_code());
5467 } while (++flags != 0);
5470 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5471 if (spdy_version_ <= SPDY3) {
5472 return;
5475 uint8 flags = 0;
5476 do {
5477 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5479 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5480 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5481 SpdyFramer framer(spdy_version_);
5482 framer.set_visitor(&visitor);
5483 framer.set_debug_visitor(&debug_visitor);
5485 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5487 SpdyPushPromiseIR push_promise(42, 57);
5488 push_promise.SetHeader("foo", "bar");
5489 scoped_ptr<SpdySerializedFrame> frame(
5490 framer.SerializePushPromise(push_promise));
5491 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5492 // and implement framing.
5493 SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
5495 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5496 EXPECT_CALL(visitor, OnError(_));
5497 } else {
5498 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5499 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5500 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5501 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5502 .WillRepeatedly(testing::Return(true));
5505 framer.ProcessInput(frame->data(), frame->size());
5506 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5507 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5508 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5509 framer.error_code())
5510 << SpdyFramer::ErrorCodeToString(framer.error_code());
5511 } else {
5512 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5513 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5514 << SpdyFramer::ErrorCodeToString(framer.error_code());
5516 } while (++flags != 0);
5519 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5520 if (spdy_version_ <= SPDY3) {
5521 return;
5524 uint8 flags = 0;
5525 do {
5526 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5528 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5529 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5530 SpdyFramer framer(spdy_version_);
5531 framer.set_visitor(&visitor);
5532 framer.set_debug_visitor(&debug_visitor);
5534 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5535 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5536 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false, false, false));
5537 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5538 .WillRepeatedly(testing::Return(true));
5540 SpdyHeadersIR headers_ir(42);
5541 headers_ir.SetHeader("foo", "bar");
5542 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5543 SetFrameFlags(frame0.get(), 0, spdy_version_);
5545 SpdyContinuationIR continuation(42);
5546 continuation.SetHeader("foo", "bar");
5547 scoped_ptr<SpdySerializedFrame> frame(
5548 framer.SerializeContinuation(continuation));
5549 SetFrameFlags(frame.get(), flags, spdy_version_);
5551 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5552 EXPECT_CALL(visitor, OnError(_));
5553 } else {
5554 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5555 EXPECT_CALL(visitor, OnContinuation(42,
5556 flags & HEADERS_FLAG_END_HEADERS));
5557 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5558 .WillRepeatedly(testing::Return(true));
5561 framer.ProcessInput(frame0->data(), frame0->size());
5562 framer.ProcessInput(frame->data(), frame->size());
5563 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5564 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5565 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5566 framer.error_code())
5567 << SpdyFramer::ErrorCodeToString(framer.error_code());
5568 } else {
5569 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5570 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5571 << SpdyFramer::ErrorCodeToString(framer.error_code());
5573 } while (++flags != 0);
5576 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5578 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5580 TEST_P(SpdyFramerTest, EmptySynStream) {
5581 if (!IsSpdy2() && !IsSpdy3()) {
5582 // SYN_STREAM not supported in SPDY>3.
5583 return;
5585 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5586 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5587 SpdyFramer framer(spdy_version_);
5588 framer.set_visitor(&visitor);
5589 framer.set_debug_visitor(&debug_visitor);
5591 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5593 SpdySynStreamIR syn_stream(1);
5594 syn_stream.set_priority(1);
5595 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5596 // Adjust size to remove the name/value block.
5597 SetFrameLength(
5598 frame.get(),
5599 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5600 spdy_version_);
5602 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5603 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5604 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5606 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5607 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5608 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5609 << SpdyFramer::ErrorCodeToString(framer.error_code());
5612 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5613 const uint32 kId = 0x020304;
5614 const uint32 kFlags = 0x01;
5615 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5617 SettingsFlagsAndId id_and_flags =
5618 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5619 EXPECT_EQ(kId, id_and_flags.id());
5620 EXPECT_EQ(kFlags, id_and_flags.flags());
5621 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5624 // Test handling of a RST_STREAM with out-of-bounds status codes.
5625 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5626 const unsigned char kRstStreamStatusTooLow = 0x00;
5627 const unsigned char kRstStreamStatusTooHigh = 0xff;
5628 const unsigned char kV3RstStreamInvalid[] = {
5629 0x80, spdy_version_ch_, 0x00, 0x03,
5630 0x00, 0x00, 0x00, 0x08,
5631 0x00, 0x00, 0x00, 0x01,
5632 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5634 const unsigned char kH2RstStreamInvalid[] = {
5635 0x00, 0x00, 0x04, 0x03,
5636 0x00, 0x00, 0x00, 0x00,
5637 0x01, 0x00, 0x00, 0x00,
5638 kRstStreamStatusTooLow
5641 const unsigned char kV3RstStreamNumStatusCodes[] = {
5642 0x80, spdy_version_ch_, 0x00, 0x03,
5643 0x00, 0x00, 0x00, 0x08,
5644 0x00, 0x00, 0x00, 0x01,
5645 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5647 const unsigned char kH2RstStreamNumStatusCodes[] = {
5648 0x00, 0x00, 0x04, 0x03,
5649 0x00, 0x00, 0x00, 0x00,
5650 0x01, 0x00, 0x00, 0x00,
5651 kRstStreamStatusTooHigh
5654 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5655 SpdyFramer framer(spdy_version_);
5656 framer.set_visitor(&visitor);
5658 if (IsHttp2()) {
5659 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5660 framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
5661 arraysize(kH2RstStreamInvalid));
5662 } else {
5663 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5664 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5665 arraysize(kV3RstStreamInvalid));
5667 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5668 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5669 << SpdyFramer::ErrorCodeToString(framer.error_code());
5672 framer.Reset();
5674 if (IsHttp2()) {
5675 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5676 framer.ProcessInput(
5677 reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
5678 arraysize(kH2RstStreamNumStatusCodes));
5679 } else {
5680 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5681 framer.ProcessInput(
5682 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5683 arraysize(kV3RstStreamNumStatusCodes));
5685 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5686 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5687 << SpdyFramer::ErrorCodeToString(framer.error_code());
5690 // Test handling of GOAWAY frames with out-of-bounds status code.
5691 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5692 if (spdy_version_ <= SPDY2) {
5693 return;
5695 SpdyFramer framer(spdy_version_);
5697 const unsigned char kV3FrameData[] = {
5698 0x80, spdy_version_ch_, 0x00, 0x07,
5699 0x00, 0x00, 0x00, 0x08,
5700 0x00, 0x00, 0x00, 0x01, // Stream Id
5701 0xff, 0xff, 0xff, 0xff, // Status
5703 const unsigned char kH2FrameData[] = {
5704 0x00, 0x00, 0x0a, 0x07,
5705 0x00, 0x00, 0x00, 0x00,
5706 0x00, 0x00, 0x00, 0x00, // Stream id
5707 0x01, 0xff, 0xff, 0xff, // Status
5708 0xff, 0x47, 0x41, // Opaque Description
5710 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5711 framer.set_visitor(&visitor);
5713 if (IsSpdy3()) {
5714 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5715 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5716 arraysize(kV3FrameData));
5717 } else {
5718 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5719 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
5720 arraysize(kH2FrameData));
5722 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5723 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5724 << SpdyFramer::ErrorCodeToString(framer.error_code());
5727 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5728 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5729 const unsigned char kV2FrameData[] = {
5730 0x80, spdy_version_ch_, 0x00, 0x07,
5731 0x00, 0x00, 0x00, 0x04,
5732 0xff, 0xff, 0xff, 0xff,
5734 const unsigned char kV3FrameData[] = {
5735 0x80, spdy_version_ch_, 0x00, 0x07,
5736 0x00, 0x00, 0x00, 0x08,
5737 0xff, 0xff, 0xff, 0xff,
5738 0x00, 0x00, 0x00, 0x00,
5740 const unsigned char kH2FrameData[] = {
5741 0x00, 0x00, 0x08, 0x07,
5742 0x00, 0x00, 0x00, 0x00,
5743 0x00, 0xff, 0xff, 0xff,
5744 0xff, 0x00, 0x00, 0x00,
5745 0x00,
5748 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5749 SpdyFramer framer(spdy_version_);
5750 framer.set_visitor(&visitor);
5752 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5753 if (IsSpdy2()) {
5754 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5755 arraysize(kV2FrameData));
5756 } else if (IsSpdy3()) {
5757 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5758 arraysize(kV3FrameData));
5759 } else {
5760 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
5761 arraysize(kH2FrameData));
5763 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5764 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5765 << SpdyFramer::ErrorCodeToString(framer.error_code());
5768 TEST_P(SpdyFramerTest, OnBlocked) {
5769 if (spdy_version_ <= SPDY3) {
5770 return;
5773 const SpdyStreamId kStreamId = 0;
5775 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5776 SpdyFramer framer(spdy_version_);
5777 framer.set_visitor(&visitor);
5779 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5781 SpdyBlockedIR blocked_ir(0);
5782 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5783 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5785 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5786 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5787 << SpdyFramer::ErrorCodeToString(framer.error_code());
5790 TEST_P(SpdyFramerTest, OnAltSvc) {
5791 if (spdy_version_ <= SPDY3) {
5792 return;
5795 const SpdyStreamId kStreamId = 1;
5797 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5798 SpdyFramer framer(spdy_version_);
5799 framer.set_visitor(&visitor);
5801 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5802 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5803 42, 0.2);
5804 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5805 altsvc_vector.push_back(altsvc1);
5806 altsvc_vector.push_back(altsvc2);
5807 EXPECT_CALL(visitor,
5808 OnAltSvc(kStreamId, StringPiece("o_r|g!n"), altsvc_vector));
5810 SpdyAltSvcIR altsvc_ir(1);
5811 altsvc_ir.set_origin("o_r|g!n");
5812 altsvc_ir.add_altsvc(altsvc1);
5813 altsvc_ir.add_altsvc(altsvc2);
5814 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5815 framer.ProcessInput(frame->data(), frame->size());
5817 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5818 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5819 << SpdyFramer::ErrorCodeToString(framer.error_code());
5822 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5823 if (spdy_version_ <= SPDY3) {
5824 return;
5827 const SpdyStreamId kStreamId = 1;
5829 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5830 SpdyFramer framer(spdy_version_);
5831 framer.set_visitor(&visitor);
5833 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5834 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5835 42, 0.2);
5836 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5837 altsvc_vector.push_back(altsvc1);
5838 altsvc_vector.push_back(altsvc2);
5839 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece(""), altsvc_vector));
5841 SpdyAltSvcIR altsvc_ir(1);
5842 altsvc_ir.add_altsvc(altsvc1);
5843 altsvc_ir.add_altsvc(altsvc2);
5844 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5845 framer.ProcessInput(frame->data(), frame->size());
5847 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5848 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5849 << SpdyFramer::ErrorCodeToString(framer.error_code());
5852 TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
5853 if (spdy_version_ <= SPDY3) {
5854 return;
5857 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5858 SpdyFramer framer(spdy_version_);
5859 framer.set_visitor(&visitor);
5861 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
5863 SpdyAltSvcIR altsvc_ir(1);
5864 altsvc_ir.set_origin("o1");
5865 altsvc_ir.add_altsvc(
5866 SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0));
5867 altsvc_ir.add_altsvc(
5868 SpdyAltSvcWireFormat::AlternativeService("", "h1", 443, 10, 1.0));
5869 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5870 framer.ProcessInput(frame->data(), frame->size());
5872 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5873 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
5874 << SpdyFramer::ErrorCodeToString(framer.error_code());
5877 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5878 if (spdy_version_ <= SPDY3) {
5879 return;
5882 const SpdyStreamId kStreamId = 1;
5884 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5885 SpdyFramer framer(spdy_version_);
5886 framer.set_visitor(&visitor);
5888 SpdyAltSvcWireFormat::AlternativeService altsvc("pid", "h1", 443, 10, 1.0);
5889 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5890 altsvc_vector.push_back(altsvc);
5891 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece("o1"), altsvc_vector));
5893 SpdyAltSvcIR altsvc_ir(1);
5894 altsvc_ir.set_origin("o1");
5895 altsvc_ir.add_altsvc(altsvc);
5896 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5897 framer.ProcessInput(frame->data(), frame->size());
5899 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5900 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5901 << SpdyFramer::ErrorCodeToString(framer.error_code());
5904 // Tests handling of ALTSVC frames delivered in small chunks.
5905 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5906 if (spdy_version_ <= SPDY3) {
5907 return;
5910 SpdyFramer framer(spdy_version_);
5911 SpdyAltSvcIR altsvc_ir(1);
5912 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5913 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5914 42, 0.2);
5915 altsvc_ir.add_altsvc(altsvc1);
5916 altsvc_ir.add_altsvc(altsvc2);
5918 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5919 TestSpdyVisitor visitor(spdy_version_);
5920 visitor.use_compression_ = false;
5922 // Read data in small chunks.
5923 size_t framed_data = 0;
5924 size_t unframed_data = control_frame->size();
5925 size_t kReadChunkSize = 5; // Read five bytes at a time.
5926 while (unframed_data > 0) {
5927 size_t to_read = std::min(kReadChunkSize, unframed_data);
5928 visitor.SimulateInFramer(
5929 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5930 to_read);
5931 unframed_data -= to_read;
5932 framed_data += to_read;
5934 EXPECT_EQ(0, visitor.error_count_);
5935 EXPECT_EQ(1, visitor.altsvc_count_);
5936 ASSERT_EQ(2u, visitor.test_altsvc_ir_.altsvc_vector().size());
5937 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[0] == altsvc1);
5938 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[1] == altsvc2);
5941 // Tests handling of PRIORITY frames.
5942 TEST_P(SpdyFramerTest, ReadPriority) {
5943 if (spdy_version_ <= SPDY3) {
5944 return;
5946 SpdyFramer framer(spdy_version_);
5947 SpdyPriorityIR priority(3, 1, 255, false);
5948 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5949 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5950 framer.set_visitor(&visitor);
5951 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5952 framer.ProcessInput(frame->data(), frame->size());
5954 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5955 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5956 << SpdyFramer::ErrorCodeToString(framer.error_code());
5957 // TODO(mlavan): once we actually maintain a priority tree,
5958 // check that state is adjusted correctly.
5961 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5962 if (spdy_version_ <= SPDY3) {
5963 return;
5965 SpdyFramer framer(spdy_version_);
5967 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5968 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5969 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5970 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5971 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5972 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5973 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5974 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5976 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5977 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5978 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5979 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5980 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5981 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5982 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5983 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5984 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5985 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5986 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5987 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5988 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5989 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5990 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5993 // Tests handling of PRIORITY frame with incorrect size.
5994 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5995 if (spdy_version_ <= SPDY3) {
5996 return;
5999 // PRIORITY frame of size 4, which isn't correct.
6000 const unsigned char kFrameData[] = {
6001 0x00, 0x00, 0x04, 0x02, 0x00,
6002 0x00, 0x00, 0x00, 0x03,
6003 0x00, 0x00, 0x00, 0x01,
6006 TestSpdyVisitor visitor(spdy_version_);
6007 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
6009 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
6010 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
6011 visitor.framer_.error_code())
6012 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
6015 } // namespace test
6017 } // namespace net