Replace SpdyNameValueBlock typedef with SpdyHeaderBlock.
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob0269894d15926f1f70294b06fb6284670b9897de
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_READY_FOR_FRAME, 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.header_block(), &visitor.headers_));
723 EXPECT_EQ(1u, visitor.headers_.size());
724 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
727 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
728 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
729 SpdyFramer framer(spdy_version_);
730 framer.set_enable_compression(false);
732 // Encode the header block into a Headers frame.
733 SpdyHeadersIR headers(1);
734 headers.set_priority(1);
735 headers.SetHeader("alpha", "beta");
736 headers.SetHeader("gamma", "charlie");
737 headers.SetHeader("cookie", "key1=value1; key2=value2");
738 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
739 EXPECT_TRUE(frame.get() != NULL);
741 TestSpdyVisitor visitor(spdy_version_);
742 visitor.use_compression_ = false;
743 visitor.SimulateInFramer(
744 reinterpret_cast<unsigned char*>(frame->data()),
745 frame->size());
747 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
748 EXPECT_TRUE(CompareHeaderBlocks(&headers.header_block(), &visitor.headers_));
751 // Test that if there's not a full frame, we fail to parse it.
752 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
753 SpdyFramer framer(spdy_version_);
754 framer.set_enable_compression(false);
756 // Encode the header block into a Headers frame.
757 SpdyHeadersIR headers(1);
758 headers.set_priority(1);
759 headers.SetHeader("alpha", "beta");
760 headers.SetHeader("gamma", "charlie");
761 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
762 EXPECT_TRUE(frame.get() != NULL);
764 TestSpdyVisitor visitor(spdy_version_);
765 visitor.use_compression_ = false;
766 visitor.SimulateInFramer(
767 reinterpret_cast<unsigned char*>(frame->data()),
768 frame->size() - 2);
770 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
771 EXPECT_EQ(0u, visitor.headers_.size());
774 // Test that we can encode and decode stream dependency values in a header
775 // frame.
776 TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
777 if (spdy_version_ <= SPDY3) {
778 return;
780 SpdyFramer framer(spdy_version_);
781 framer.set_enable_compression(false);
783 const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
784 for (SpdyStreamId parent_stream_id : parent_stream_id_test_array) {
785 const bool exclusive_test_array[] = {true, false};
786 for (bool exclusive : exclusive_test_array) {
787 SpdyHeadersIR headers(1);
788 headers.set_has_priority(true);
789 headers.set_parent_stream_id(parent_stream_id);
790 headers.set_exclusive(exclusive);
791 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
792 EXPECT_TRUE(frame.get() != NULL);
794 TestSpdyVisitor visitor(spdy_version_);
795 visitor.use_compression_ = false;
796 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame->data()),
797 frame->size());
799 EXPECT_TRUE(visitor.header_has_priority_);
800 EXPECT_EQ(parent_stream_id, visitor.header_parent_stream_id_);
801 EXPECT_EQ(exclusive, visitor.header_exclusive_);
806 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
807 // (but don't crash).
808 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
809 if (spdy_version_ > SPDY3) {
810 return;
812 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
813 SpdyFramer framer(spdy_version_);
814 framer.set_visitor(&visitor);
816 SpdySynReplyIR syn_reply(0);
817 syn_reply.SetHeader("alpha", "beta");
818 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
819 ASSERT_TRUE(frame.get() != NULL);
821 // We shouldn't have to read the whole frame before we signal an error.
822 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
823 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
824 EXPECT_TRUE(framer.HasError());
825 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
826 << SpdyFramer::ErrorCodeToString(framer.error_code());
829 // Test that if we receive a HEADERS with stream ID zero, we signal an error
830 // (but don't crash).
831 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
832 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
833 SpdyFramer framer(spdy_version_);
834 framer.set_visitor(&visitor);
836 SpdyHeadersIR headers_ir(0);
837 headers_ir.SetHeader("alpha", "beta");
838 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
839 ASSERT_TRUE(frame.get() != NULL);
841 // We shouldn't have to read the whole frame before we signal an error.
842 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
843 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
844 EXPECT_TRUE(framer.HasError());
845 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
846 << SpdyFramer::ErrorCodeToString(framer.error_code());
849 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
850 // error (but don't crash).
851 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
852 if (spdy_version_ <= SPDY3) {
853 return;
856 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
857 SpdyFramer framer(spdy_version_);
858 framer.set_visitor(&visitor);
860 SpdyPushPromiseIR push_promise(0, 4);
861 push_promise.SetHeader("alpha", "beta");
862 scoped_ptr<SpdySerializedFrame> frame(
863 framer.SerializePushPromise(push_promise));
864 ASSERT_TRUE(frame.get() != NULL);
866 // We shouldn't have to read the whole frame before we signal an error.
867 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
868 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
869 EXPECT_TRUE(framer.HasError());
870 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
871 << SpdyFramer::ErrorCodeToString(framer.error_code());
874 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
875 // signal an error (but don't crash).
876 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
877 if (spdy_version_ <= SPDY3) {
878 return;
881 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
882 SpdyFramer framer(spdy_version_);
883 framer.set_visitor(&visitor);
885 SpdyPushPromiseIR push_promise(3, 0);
886 push_promise.SetHeader("alpha", "beta");
887 scoped_ptr<SpdySerializedFrame> frame(
888 framer.SerializePushPromise(push_promise));
889 ASSERT_TRUE(frame.get() != NULL);
891 // We shouldn't have to read the whole frame before we signal an error.
892 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
893 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
894 EXPECT_TRUE(framer.HasError());
895 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
896 << SpdyFramer::ErrorCodeToString(framer.error_code());
899 TEST_P(SpdyFramerTest, DuplicateHeader) {
900 if (spdy_version_ > SPDY3) {
901 // TODO(jgraettinger): Punting on this because we haven't determined
902 // whether duplicate HPACK headers other than Cookie are an error.
903 // If they are, this will need to be updated to use HpackOutputStream.
904 return;
906 SpdyFramer framer(spdy_version_);
907 // Frame builder with plentiful buffer size.
908 SpdyFrameBuilder frame(1024, spdy_version_);
909 if (spdy_version_ <= SPDY3) {
910 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
911 frame.WriteUInt32(3); // stream_id
912 frame.WriteUInt32(0); // associated stream id
913 frame.WriteUInt16(0); // Priority.
914 } else {
915 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
916 frame.WriteUInt32(framer.GetHighestPriority());
919 if (IsSpdy2()) {
920 frame.WriteUInt16(2); // Number of headers.
921 frame.WriteStringPiece16("name");
922 frame.WriteStringPiece16("value1");
923 frame.WriteStringPiece16("name");
924 frame.WriteStringPiece16("value2");
925 } else {
926 frame.WriteUInt32(2); // Number of headers.
927 frame.WriteStringPiece32("name");
928 frame.WriteStringPiece32("value1");
929 frame.WriteStringPiece32("name");
930 frame.WriteStringPiece32("value2");
932 // write the length
933 frame.RewriteLength(framer);
935 SpdyHeaderBlock new_headers;
936 framer.set_enable_compression(false);
937 scoped_ptr<SpdyFrame> control_frame(frame.take());
938 base::StringPiece serialized_headers =
939 GetSerializedHeaders(control_frame.get(), framer);
940 // This should fail because duplicate headers are verboten by the spec.
941 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
942 serialized_headers.size(),
943 &new_headers));
946 TEST_P(SpdyFramerTest, MultiValueHeader) {
947 SpdyFramer framer(spdy_version_);
948 // Frame builder with plentiful buffer size.
949 SpdyFrameBuilder frame(1024, spdy_version_);
950 if (spdy_version_ <= SPDY3) {
951 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
952 frame.WriteUInt32(3); // stream_id
953 frame.WriteUInt32(0); // associated stream id
954 frame.WriteUInt16(0); // Priority.
955 } else {
956 frame.BeginNewFrame(framer,
957 HEADERS,
958 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
960 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
961 frame.WriteUInt8(255); // Priority weight.
964 string value("value1\0value2", 13);
965 if (IsSpdy2()) {
966 frame.WriteUInt16(1); // Number of headers.
967 frame.WriteStringPiece16("name");
968 frame.WriteStringPiece16(value);
969 } else if (spdy_version_ > SPDY3) {
970 // TODO(jgraettinger): If this pattern appears again, move to test class.
971 SpdyHeaderBlock header_set;
972 header_set["name"] = value;
973 string buffer;
974 HpackEncoder encoder(ObtainHpackHuffmanTable());
975 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
976 frame.WriteBytes(&buffer[0], buffer.size());
977 } else {
978 frame.WriteUInt32(1); // Number of headers.
979 frame.WriteStringPiece32("name");
980 frame.WriteStringPiece32(value);
982 // write the length
983 frame.RewriteLength(framer);
985 framer.set_enable_compression(false);
986 scoped_ptr<SpdyFrame> control_frame(frame.take());
988 TestSpdyVisitor visitor(spdy_version_);
989 visitor.use_compression_ = false;
990 visitor.SimulateInFramer(
991 reinterpret_cast<unsigned char*>(control_frame->data()),
992 control_frame->size());
994 EXPECT_THAT(visitor.headers_,
995 testing::ElementsAre(testing::Pair("name", value)));
998 TEST_P(SpdyFramerTest, BasicCompression) {
999 if (spdy_version_ > SPDY3) {
1000 // Deflate compression doesn't apply to HPACK.
1001 return;
1003 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
1004 SpdyFramer framer(spdy_version_);
1005 framer.set_debug_visitor(visitor.get());
1006 SpdySynStreamIR syn_stream(1);
1007 syn_stream.set_priority(1);
1008 syn_stream.SetHeader("server", "SpdyServer 1.0");
1009 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1010 syn_stream.SetHeader("status", "200");
1011 syn_stream.SetHeader("version", "HTTP/1.1");
1012 syn_stream.SetHeader("content-type", "text/html");
1013 syn_stream.SetHeader("content-length", "12");
1014 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
1015 size_t uncompressed_size1 = visitor->last_payload_len_;
1016 size_t compressed_size1 =
1017 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1018 if (IsSpdy2()) {
1019 EXPECT_EQ(139u, uncompressed_size1);
1020 #if defined(USE_SYSTEM_ZLIB)
1021 EXPECT_EQ(155u, compressed_size1);
1022 #else // !defined(USE_SYSTEM_ZLIB)
1023 EXPECT_EQ(135u, compressed_size1);
1024 #endif // !defined(USE_SYSTEM_ZLIB)
1025 } else {
1026 EXPECT_EQ(165u, uncompressed_size1);
1027 #if defined(USE_SYSTEM_ZLIB)
1028 EXPECT_EQ(181u, compressed_size1);
1029 #else // !defined(USE_SYSTEM_ZLIB)
1030 EXPECT_EQ(117u, compressed_size1);
1031 #endif // !defined(USE_SYSTEM_ZLIB)
1033 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
1034 size_t uncompressed_size2 = visitor->last_payload_len_;
1035 size_t compressed_size2 =
1036 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1038 // Expect the second frame to be more compact than the first.
1039 EXPECT_LE(frame2->size(), frame1->size());
1041 // Decompress the first frame
1042 scoped_ptr<SpdyFrame> frame3(
1043 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
1045 // Decompress the second frame
1046 visitor.reset(new TestSpdyVisitor(spdy_version_));
1047 framer.set_debug_visitor(visitor.get());
1048 scoped_ptr<SpdyFrame> frame4(
1049 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1050 size_t uncompressed_size4 =
1051 frame4->size() - framer.GetSynStreamMinimumSize();
1052 size_t compressed_size4 =
1053 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1054 if (IsSpdy2()) {
1055 EXPECT_EQ(139u, uncompressed_size4);
1056 #if defined(USE_SYSTEM_ZLIB)
1057 EXPECT_EQ(149u, compressed_size4);
1058 #else // !defined(USE_SYSTEM_ZLIB)
1059 EXPECT_EQ(101u, compressed_size4);
1060 #endif // !defined(USE_SYSTEM_ZLIB)
1061 } else {
1062 EXPECT_EQ(165u, uncompressed_size4);
1063 #if defined(USE_SYSTEM_ZLIB)
1064 EXPECT_EQ(175u, compressed_size4);
1065 #else // !defined(USE_SYSTEM_ZLIB)
1066 EXPECT_EQ(102u, compressed_size4);
1067 #endif // !defined(USE_SYSTEM_ZLIB)
1070 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1071 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1072 EXPECT_EQ(compressed_size2, compressed_size4);
1074 // Expect frames 3 & 4 to be the same.
1075 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1077 // Expect frames 3 to be the same as a uncompressed frame created
1078 // from scratch.
1079 framer.set_enable_compression(false);
1080 scoped_ptr<SpdyFrame> uncompressed_frame(
1081 framer.SerializeSynStream(syn_stream));
1082 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1085 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1086 // See crbug.com/172383
1087 SpdyHeadersIR headers(1);
1088 headers.SetHeader("server", "SpdyServer 1.0");
1089 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1090 headers.SetHeader("status", "200");
1091 headers.SetHeader("version", "HTTP/1.1");
1092 headers.SetHeader("content-type", "text/html");
1093 headers.SetHeader("content-length", "12");
1094 headers.SetHeader("x-empty-header", "");
1096 SpdyFramer framer(spdy_version_);
1097 framer.set_enable_compression(true);
1098 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1101 TEST_P(SpdyFramerTest, Basic) {
1102 const unsigned char kV2Input[] = {
1103 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1104 0x00, 0x00, 0x00, 0x14,
1105 0x00, 0x00, 0x00, 0x01,
1106 0x00, 0x00, 0x00, 0x00,
1107 0x00, 0x00, 0x00, 0x01,
1108 0x00, 0x02, 'h', 'h',
1109 0x00, 0x02, 'v', 'v',
1111 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1112 0x00, 0x00, 0x00, 0x18,
1113 0x00, 0x00, 0x00, 0x01,
1114 0x00, 0x00, 0x00, 0x02,
1115 0x00, 0x02, 'h', '2',
1116 0x00, 0x02, 'v', '2',
1117 0x00, 0x02, 'h', '3',
1118 0x00, 0x02, 'v', '3',
1120 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1121 0x00, 0x00, 0x00, 0x0c,
1122 0xde, 0xad, 0xbe, 0xef,
1123 0xde, 0xad, 0xbe, 0xef,
1124 0xde, 0xad, 0xbe, 0xef,
1126 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1127 0x00, 0x00, 0x00, 0x0c,
1128 0x00, 0x00, 0x00, 0x03,
1129 0x00, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00,
1132 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1133 0x00, 0x00, 0x00, 0x08,
1134 0xde, 0xad, 0xbe, 0xef,
1135 0xde, 0xad, 0xbe, 0xef,
1137 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1138 0x00, 0x00, 0x00, 0x04,
1139 0xde, 0xad, 0xbe, 0xef,
1141 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1142 0x00, 0x00, 0x00, 0x08,
1143 0x00, 0x00, 0x00, 0x01,
1144 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1146 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1147 0x00, 0x00, 0x00, 0x00,
1149 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1150 0x00, 0x00, 0x00, 0x08,
1151 0x00, 0x00, 0x00, 0x03,
1152 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1155 const unsigned char kV3Input[] = {
1156 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1157 0x00, 0x00, 0x00, 0x1a,
1158 0x00, 0x00, 0x00, 0x01,
1159 0x00, 0x00, 0x00, 0x00,
1160 0x00, 0x00, 0x00, 0x00,
1161 0x00, 0x01, 0x00, 0x00,
1162 0x00, 0x02, 'h', 'h',
1163 0x00, 0x00, 0x00, 0x02,
1164 'v', 'v',
1166 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1167 0x00, 0x00, 0x00, 0x20,
1168 0x00, 0x00, 0x00, 0x01,
1169 0x00, 0x00, 0x00, 0x02,
1170 0x00, 0x00, 0x00, 0x02,
1171 'h', '2',
1172 0x00, 0x00, 0x00, 0x02,
1173 'v', '2', 0x00, 0x00,
1174 0x00, 0x02, 'h', '3',
1175 0x00, 0x00, 0x00, 0x02,
1176 'v', '3',
1178 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1179 0x00, 0x00, 0x00, 0x0c,
1180 0xde, 0xad, 0xbe, 0xef,
1181 0xde, 0xad, 0xbe, 0xef,
1182 0xde, 0xad, 0xbe, 0xef,
1184 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1185 0x00, 0x00, 0x00, 0x0e,
1186 0x00, 0x00, 0x00, 0x03,
1187 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00,
1189 0x00, 0x00,
1191 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1192 0x00, 0x00, 0x00, 0x08,
1193 0xde, 0xad, 0xbe, 0xef,
1194 0xde, 0xad, 0xbe, 0xef,
1196 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1197 0x00, 0x00, 0x00, 0x04,
1198 0xde, 0xad, 0xbe, 0xef,
1200 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1201 0x00, 0x00, 0x00, 0x08,
1202 0x00, 0x00, 0x00, 0x01,
1203 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1205 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1206 0x00, 0x00, 0x00, 0x00,
1208 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1209 0x00, 0x00, 0x00, 0x08,
1210 0x00, 0x00, 0x00, 0x03,
1211 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1214 // SYN_STREAM doesn't exist in HTTP/2, so instead we send
1215 // HEADERS frames with PRIORITY and END_HEADERS set.
1216 const unsigned char kH2Input[] = {
1217 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1218 0x24, 0x00, 0x00, 0x00,
1219 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1220 0x00, 0x82, // :method: GET
1222 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1223 0x04, 0x00, 0x00, 0x00, // Stream 1
1224 0x01, 0x8c, // :status: 200
1226 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1227 0x00, 0x00, 0x00, 0x00,
1228 0x01, 0xde, 0xad, 0xbe,
1229 0xef, 0xde, 0xad, 0xbe,
1230 0xef, 0xde, 0xad, 0xbe,
1231 0xef,
1233 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1234 0x24, 0x00, 0x00, 0x00,
1235 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1236 0x00, 0x82, // :method: GET
1238 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1239 0x00, 0x00, 0x00, 0x00,
1240 0x03, 0xde, 0xad, 0xbe,
1241 0xef, 0xde, 0xad, 0xbe,
1242 0xef,
1244 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1245 0x00, 0x00, 0x00, 0x00,
1246 0x01, 0xde, 0xad, 0xbe,
1247 0xef,
1249 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1250 0x00, 0x00, 0x00, 0x00,
1251 0x01, 0x00, 0x00, 0x00,
1252 0x08, // RST_STREAM_CANCEL
1254 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1255 0x00, 0x00, 0x00, 0x00,
1256 0x03,
1258 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1259 0x00, 0x00, 0x00, 0x00,
1260 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1261 0x08, 0x52, 0x45, 0x53, // opaque data
1262 0x45, 0x54, 0x53, 0x54,
1263 0x52, 0x45, 0x41, 0x4d,
1266 TestSpdyVisitor visitor(spdy_version_);
1267 if (IsSpdy2()) {
1268 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1269 } else if (IsSpdy3()) {
1270 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1271 } else {
1272 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1275 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1276 EXPECT_EQ(24, visitor.data_bytes_);
1277 EXPECT_EQ(0, visitor.error_count_);
1278 EXPECT_EQ(2, visitor.fin_frame_count_);
1280 if (IsHttp2()) {
1281 EXPECT_EQ(3, visitor.headers_frame_count_);
1282 EXPECT_EQ(0, visitor.syn_frame_count_);
1283 base::StringPiece reset_stream = "RESETSTREAM";
1284 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1285 } else {
1286 EXPECT_EQ(1, visitor.headers_frame_count_);
1287 EXPECT_EQ(2, visitor.syn_frame_count_);
1288 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1291 EXPECT_EQ(0, visitor.fin_flag_count_);
1292 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1293 EXPECT_EQ(4, visitor.data_frame_count_);
1294 visitor.fin_opaque_data_.clear();
1297 // Test that the FIN flag on a data frame signifies EOF.
1298 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1299 const unsigned char kV2Input[] = {
1300 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1301 0x00, 0x00, 0x00, 0x14,
1302 0x00, 0x00, 0x00, 0x01,
1303 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x01,
1305 0x00, 0x02, 'h', 'h',
1306 0x00, 0x02, 'v', 'v',
1308 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1309 0x00, 0x00, 0x00, 0x10,
1310 0x00, 0x00, 0x00, 0x01,
1311 0x00, 0x00, 0x00, 0x01,
1312 0x00, 0x02, 'a', 'a',
1313 0x00, 0x02, 'b', 'b',
1315 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1316 0x00, 0x00, 0x00, 0x0c,
1317 0xde, 0xad, 0xbe, 0xef,
1318 0xde, 0xad, 0xbe, 0xef,
1319 0xde, 0xad, 0xbe, 0xef,
1321 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1322 0x01, 0x00, 0x00, 0x04,
1323 0xde, 0xad, 0xbe, 0xef,
1325 const unsigned char kV3Input[] = {
1326 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1327 0x00, 0x00, 0x00, 0x1a,
1328 0x00, 0x00, 0x00, 0x01,
1329 0x00, 0x00, 0x00, 0x00,
1330 0x00, 0x00, 0x00, 0x00,
1331 0x00, 0x01, 0x00, 0x00,
1332 0x00, 0x02, 'h', 'h',
1333 0x00, 0x00, 0x00, 0x02,
1334 'v', 'v',
1336 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1337 0x00, 0x00, 0x00, 0x14,
1338 0x00, 0x00, 0x00, 0x01,
1339 0x00, 0x00, 0x00, 0x01,
1340 0x00, 0x00, 0x00, 0x02,
1341 'a', 'a', 0x00, 0x00,
1342 0x00, 0x02, 'b', 'b',
1344 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1345 0x00, 0x00, 0x00, 0x0c,
1346 0xde, 0xad, 0xbe, 0xef,
1347 0xde, 0xad, 0xbe, 0xef,
1348 0xde, 0xad, 0xbe, 0xef,
1350 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1351 0x01, 0x00, 0x00, 0x04,
1352 0xde, 0xad, 0xbe, 0xef,
1355 // SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
1356 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1357 const unsigned char kH2Input[] = {
1358 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1359 0x24, 0x00, 0x00, 0x00, // Stream 1
1360 0x01, 0x00, 0x00, 0x00, // Priority 0
1361 0x00, 0x82, // :method: GET
1363 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1364 0x04, 0x00, 0x00, 0x00, // Stream 1
1365 0x01, 0x8c, // :status: 200
1367 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1368 0x00, 0x00, 0x00, 0x00,
1369 0x01, 0xde, 0xad, 0xbe,
1370 0xef, 0xde, 0xad, 0xbe,
1371 0xef, 0xde, 0xad, 0xbe,
1372 0xef,
1374 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1375 0x01, 0x00, 0x00, 0x00,
1376 0x01, 0xde, 0xad, 0xbe,
1377 0xef,
1380 TestSpdyVisitor visitor(spdy_version_);
1381 if (IsSpdy2()) {
1382 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1383 } else if (IsSpdy3()) {
1384 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1385 } else {
1386 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1389 EXPECT_EQ(0, visitor.error_count_);
1390 if (IsHttp2()) {
1391 EXPECT_EQ(0, visitor.syn_frame_count_);
1392 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1393 EXPECT_EQ(2, visitor.headers_frame_count_);
1394 } else {
1395 EXPECT_EQ(1, visitor.syn_frame_count_);
1396 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1397 EXPECT_EQ(0, visitor.headers_frame_count_);
1399 EXPECT_EQ(16, visitor.data_bytes_);
1400 EXPECT_EQ(0, visitor.fin_frame_count_);
1401 EXPECT_EQ(0, visitor.fin_flag_count_);
1402 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1403 EXPECT_EQ(2, visitor.data_frame_count_);
1406 // Test that the FIN flag on a SYN reply frame signifies EOF.
1407 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1408 const unsigned char kV2Input[] = {
1409 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1410 0x01, 0x00, 0x00, 0x00,
1411 0x14, 0x00, 0x00, 0x00,
1412 0x01, 0x00, 0x00, 0x00,
1413 0x00, 0x00, 0x00, 0x00,
1414 0x01, 0x00, 0x02, 'h',
1415 'h', 0x00, 0x02, 'v',
1416 'v',
1418 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1419 0x02, 0x01, 0x00, 0x00,
1420 0x10, 0x00, 0x00, 0x00,
1421 0x01, 0x00, 0x00, 0x00,
1422 0x01, 0x00, 0x02, 'a',
1423 'a', 0x00, 0x02, 'b',
1424 'b',
1426 const unsigned char kV3Input[] = {
1427 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1428 0x01, 0x00, 0x00, 0x00,
1429 0x1a, 0x00, 0x00, 0x00,
1430 0x01, 0x00, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00,
1432 0x00, 0x00, 0x01, 0x00,
1433 0x00, 0x00, 0x02, 'h',
1434 'h', 0x00, 0x00, 0x00,
1435 0x02, 'v', 'v',
1437 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1438 0x02, 0x01, 0x00, 0x00,
1439 0x14, 0x00, 0x00, 0x00,
1440 0x01, 0x00, 0x00, 0x00,
1441 0x01, 0x00, 0x00, 0x00,
1442 0x02, 'a', 'a', 0x00,
1443 0x00, 0x00, 0x02, 'b',
1444 'b',
1447 // SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
1448 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1449 const unsigned char kH2Input[] = {
1450 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1451 0x24, 0x00, 0x00, 0x00,
1452 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1453 0x00, 0x82, // :method: GET
1455 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1456 0x05, 0x00, 0x00, 0x00,
1457 0x01, 0x8c, // Stream 1, :status: 200
1460 TestSpdyVisitor visitor(spdy_version_);
1461 if (IsSpdy2()) {
1462 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1463 } else if (IsSpdy3()) {
1464 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1465 } else {
1466 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1469 EXPECT_EQ(0, visitor.error_count_);
1470 if (IsHttp2()) {
1471 EXPECT_EQ(0, visitor.syn_frame_count_);
1472 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1473 EXPECT_EQ(2, visitor.headers_frame_count_);
1474 } else {
1475 EXPECT_EQ(1, visitor.syn_frame_count_);
1476 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1477 EXPECT_EQ(0, visitor.headers_frame_count_);
1479 EXPECT_EQ(0, visitor.data_bytes_);
1480 EXPECT_EQ(0, visitor.fin_frame_count_);
1481 EXPECT_EQ(1, visitor.fin_flag_count_);
1482 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1483 EXPECT_EQ(0, visitor.data_frame_count_);
1486 TEST_P(SpdyFramerTest, HeaderCompression) {
1487 if (spdy_version_ > SPDY3) {
1488 // Deflate compression doesn't apply to HPACK.
1489 return;
1491 SpdyFramer send_framer(spdy_version_);
1492 SpdyFramer recv_framer(spdy_version_);
1494 send_framer.set_enable_compression(true);
1495 recv_framer.set_enable_compression(true);
1497 const char kHeader1[] = "header1";
1498 const char kHeader2[] = "header2";
1499 const char kHeader3[] = "header3";
1500 const char kValue1[] = "value1";
1501 const char kValue2[] = "value2";
1502 const char kValue3[] = "value3";
1504 // SYN_STREAM #1
1505 SpdyHeaderBlock block;
1506 block[kHeader1] = kValue1;
1507 block[kHeader2] = kValue2;
1508 SpdySynStreamIR syn_ir_1(1);
1509 syn_ir_1.set_header_block(block);
1510 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1511 EXPECT_TRUE(syn_frame_1.get() != NULL);
1513 // SYN_STREAM #2
1514 block[kHeader3] = kValue3;
1515 SpdySynStreamIR syn_stream(3);
1516 syn_stream.set_header_block(block);
1517 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1518 EXPECT_TRUE(syn_frame_2.get() != NULL);
1520 // Now start decompressing
1521 scoped_ptr<SpdyFrame> decompressed;
1522 scoped_ptr<SpdyFrame> uncompressed;
1523 base::StringPiece serialized_headers;
1524 SpdyHeaderBlock decompressed_headers;
1526 // Decompress SYN_STREAM #1
1527 decompressed.reset(
1528 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1529 EXPECT_TRUE(decompressed.get() != NULL);
1530 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1531 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1532 serialized_headers.size(),
1533 &decompressed_headers));
1534 EXPECT_EQ(2u, decompressed_headers.size());
1535 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1536 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1538 // Decompress SYN_STREAM #2
1539 decompressed.reset(
1540 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1541 EXPECT_TRUE(decompressed.get() != NULL);
1542 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1543 decompressed_headers.clear();
1544 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1545 serialized_headers.size(),
1546 &decompressed_headers));
1547 EXPECT_EQ(3u, decompressed_headers.size());
1548 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1549 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1550 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1553 // Verify we can decompress the stream even if handed over to the
1554 // framer 1 byte at a time.
1555 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1556 SpdyFramer send_framer(spdy_version_);
1558 send_framer.set_enable_compression(true);
1560 const char kHeader1[] = "header1";
1561 const char kHeader2[] = "header2";
1562 const char kValue1[] = "value1";
1563 const char kValue2[] = "value2";
1565 SpdyHeadersIR headers(1);
1566 headers.SetHeader(kHeader1, kValue1);
1567 headers.SetHeader(kHeader2, kValue2);
1568 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1569 EXPECT_TRUE(headers_frame.get() != NULL);
1571 const char bytes[] = "this is a test test test test test!";
1572 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1573 data_ir.set_fin(true);
1574 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1575 EXPECT_TRUE(send_frame.get() != NULL);
1577 // Run the inputs through the framer.
1578 TestSpdyVisitor visitor(spdy_version_);
1579 visitor.use_compression_ = true;
1580 const unsigned char* data;
1581 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1582 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1583 visitor.SimulateInFramer(data + idx, 1);
1584 ASSERT_EQ(0, visitor.error_count_);
1586 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1587 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1588 visitor.SimulateInFramer(data + idx, 1);
1589 ASSERT_EQ(0, visitor.error_count_);
1592 EXPECT_EQ(0, visitor.error_count_);
1593 EXPECT_EQ(0, visitor.syn_frame_count_);
1594 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1595 EXPECT_EQ(1, visitor.headers_frame_count_);
1596 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1597 EXPECT_EQ(0, visitor.fin_frame_count_);
1598 EXPECT_EQ(0, visitor.fin_flag_count_);
1599 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1600 EXPECT_EQ(1, visitor.data_frame_count_);
1603 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1604 SpdyFramer framer(spdy_version_);
1605 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1606 SpdyWindowUpdateIR(1, 0x12345678)));
1608 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1609 const unsigned char kV3FrameData[] = { // Also applies for V2.
1610 0x80, spdy_version_ch_, 0x00, 0x09,
1611 0x00, 0x00, 0x00, 0x08,
1612 0x00, 0x00, 0x00, 0x01,
1613 0x12, 0x34, 0x56, 0x78
1615 const unsigned char kH2FrameData[] = {
1616 0x00, 0x00, 0x04, 0x08,
1617 0x00, 0x00, 0x00, 0x00,
1618 0x01, 0x12, 0x34, 0x56,
1619 0x78
1622 if (IsHttp2()) {
1623 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1624 } else {
1625 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1629 TEST_P(SpdyFramerTest, CreateDataFrame) {
1630 SpdyFramer framer(spdy_version_);
1633 const char kDescription[] = "'hello' data frame, no FIN";
1634 const unsigned char kV3FrameData[] = { // Also applies for V2.
1635 0x00, 0x00, 0x00, 0x01,
1636 0x00, 0x00, 0x00, 0x05,
1637 'h', 'e', 'l', 'l',
1640 const unsigned char kH2FrameData[] = {0x00,
1641 0x00,
1642 0x05,
1643 0x00,
1644 0x00,
1645 0x00,
1646 0x00,
1647 0x00,
1648 0x01,
1649 'h',
1650 'e',
1651 'l',
1652 'l',
1653 'o'};
1654 const char bytes[] = "hello";
1656 SpdyDataIR data_ir(1, bytes);
1657 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1658 if (IsHttp2()) {
1659 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1660 } else {
1661 CompareFrame(
1662 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1665 SpdyDataIR data_header_ir(1);
1666 data_header_ir.SetDataShallow(bytes);
1667 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1668 data_header_ir));
1669 CompareCharArraysWithHexError(
1670 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1671 framer.GetDataFrameMinimumSize(),
1672 IsHttp2() ? kH2FrameData : kV3FrameData,
1673 framer.GetDataFrameMinimumSize());
1677 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1678 const unsigned char kV3FrameData[] = { // Also applies for V2.
1679 0x00, 0x00, 0x00, 0x01,
1680 0x00, 0x00, 0x00, 0x05,
1681 'h', 'e', 'l', 'l',
1685 const unsigned char kH2FrameData[] = {
1686 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1687 0x08, 0x00, 0x00, 0x00,
1688 0x01, 0xf7, // Pad length field.
1689 'h', 'e', 'l', 'l', // Data
1690 'o',
1691 // Padding of 247 0x00(s).
1692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
1714 const char bytes[] = "hello";
1716 SpdyDataIR data_ir(1, bytes);
1717 // 247 zeros and the pad length field make the overall padding to be 248
1718 // bytes.
1719 data_ir.set_padding_len(248);
1720 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1721 if (IsHttp2()) {
1722 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1723 } else {
1724 CompareFrame(
1725 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1728 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1729 CompareCharArraysWithHexError(
1730 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1731 framer.GetDataFrameMinimumSize(),
1732 IsHttp2() ? kH2FrameData : kV3FrameData,
1733 framer.GetDataFrameMinimumSize());
1737 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1738 const unsigned char kV3FrameData[] = { // Also applies for V2.
1739 0x00, 0x00, 0x00, 0x01,
1740 0x00, 0x00, 0x00, 0x05,
1741 'h', 'e', 'l', 'l',
1745 const unsigned char kH2FrameData[] = {
1746 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1747 0x08, 0x00, 0x00, 0x00,
1748 0x01, 0x07, // Pad length field.
1749 'h', 'e', 'l', 'l', // Data
1750 'o',
1751 0x00, 0x00, 0x00, 0x00, // Padding
1752 0x00, 0x00, 0x00
1754 const char bytes[] = "hello";
1756 SpdyDataIR data_ir(1, bytes);
1757 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1758 data_ir.set_padding_len(8);
1759 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1760 if (IsHttp2()) {
1761 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1762 } else {
1763 CompareFrame(
1764 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1769 const char kDescription[] =
1770 "'hello' data frame with 1 byte padding, no FIN";
1771 const unsigned char kV3FrameData[] = { // Also applies for V2.
1772 0x00, 0x00, 0x00, 0x01,
1773 0x00, 0x00, 0x00, 0x05,
1774 'h', 'e', 'l', 'l',
1778 const unsigned char kH2FrameData[] = {
1779 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1780 0x08, 0x00, 0x00, 0x00,
1781 0x01, 0x00, // Pad length field.
1782 'h', 'e', 'l', 'l', // Data
1783 'o',
1785 const char bytes[] = "hello";
1787 SpdyDataIR data_ir(1, bytes);
1788 // The pad length field itself is used for the 1-byte padding and no padding
1789 // payload is needed.
1790 data_ir.set_padding_len(1);
1791 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1792 if (IsHttp2()) {
1793 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1794 } else {
1795 CompareFrame(
1796 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1799 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1800 CompareCharArraysWithHexError(
1801 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1802 framer.GetDataFrameMinimumSize(),
1803 IsHttp2() ? kH2FrameData : kV3FrameData,
1804 framer.GetDataFrameMinimumSize());
1808 const char kDescription[] = "Data frame with negative data byte, no FIN";
1809 const unsigned char kV3FrameData[] = { // Also applies for V2.
1810 0x00, 0x00, 0x00, 0x01,
1811 0x00, 0x00, 0x00, 0x01,
1812 0xff
1814 const unsigned char kH2FrameData[] = {
1815 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff};
1816 SpdyDataIR data_ir(1, "\xff");
1817 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1818 if (IsHttp2()) {
1819 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1820 } else {
1821 CompareFrame(
1822 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1827 const char kDescription[] = "'hello' data frame, with FIN";
1828 const unsigned char kV3FrameData[] = { // Also applies for V2.
1829 0x00, 0x00, 0x00, 0x01,
1830 0x01, 0x00, 0x00, 0x05,
1831 'h', 'e', 'l', 'l',
1834 const unsigned char kH2FrameData[] = {
1835 0x00, 0x00, 0x05, 0x00,
1836 0x01, 0x00, 0x00, 0x00,
1837 0x01, 'h', 'e', 'l',
1838 'l', 'o'
1840 SpdyDataIR data_ir(1, "hello");
1841 data_ir.set_fin(true);
1842 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1843 if (IsHttp2()) {
1844 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1845 } else {
1846 CompareFrame(
1847 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1852 const char kDescription[] = "Empty data frame";
1853 const unsigned char kV3FrameData[] = { // Also applies for V2.
1854 0x00, 0x00, 0x00, 0x01,
1855 0x00, 0x00, 0x00, 0x00,
1857 const unsigned char kH2FrameData[] = {
1858 0x00, 0x00, 0x00, 0x00,
1859 0x00, 0x00, 0x00, 0x00,
1860 0x01,
1862 SpdyDataIR data_ir(1, "");
1863 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1864 if (IsHttp2()) {
1865 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1866 } else {
1867 CompareFrame(
1868 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1871 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1872 CompareCharArraysWithHexError(
1873 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1874 framer.GetDataFrameMinimumSize(),
1875 IsHttp2() ? kH2FrameData : kV3FrameData,
1876 framer.GetDataFrameMinimumSize());
1880 const char kDescription[] = "Data frame with max stream ID";
1881 const unsigned char kV3FrameData[] = { // Also applies for V2.
1882 0x7f, 0xff, 0xff, 0xff,
1883 0x01, 0x00, 0x00, 0x05,
1884 'h', 'e', 'l', 'l',
1887 const unsigned char kH2FrameData[] = {
1888 0x00, 0x00, 0x05, 0x00,
1889 0x01, 0x7f, 0xff, 0xff,
1890 0xff, 'h', 'e', 'l',
1891 'l', 'o'
1893 SpdyDataIR data_ir(0x7fffffff, "hello");
1894 data_ir.set_fin(true);
1895 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1896 if (IsHttp2()) {
1897 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1898 } else {
1899 CompareFrame(
1900 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1904 if (!IsHttp2()) {
1905 // This test does not apply to HTTP/2 because the max frame size is smaller
1906 // than 4MB.
1907 const char kDescription[] = "Large data frame";
1908 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1909 const string kData(kDataSize, 'A');
1910 const unsigned char kFrameHeader[] = {
1911 0x00, 0x00, 0x00, 0x01,
1912 0x01, 0x40, 0x00, 0x00,
1915 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1916 scoped_ptr<unsigned char[]> expected_frame_data(
1917 new unsigned char[kFrameSize]);
1918 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1919 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1921 SpdyDataIR data_ir(1, kData);
1922 data_ir.set_fin(true);
1923 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1924 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1928 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1929 if (!IsSpdy2() && !IsSpdy3()) {
1930 // SYN_STREAM unsupported in SPDY>3
1931 return;
1933 SpdyFramer framer(spdy_version_);
1934 framer.set_enable_compression(false);
1937 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1939 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1940 const unsigned char kV2FrameData[] = {
1941 0x80, spdy_version_ch_, 0x00, 0x01,
1942 0x00, 0x00, 0x00, 0x20,
1943 0x00, 0x00, 0x00, 0x01,
1944 0x00, 0x00, 0x00, 0x00,
1945 kPri, 0x00, 0x00, 0x02,
1946 0x00, 0x03, 'b', 'a',
1947 'r', 0x00, 0x03, 'f',
1948 'o', 'o', 0x00, 0x03,
1949 'f', 'o', 'o', 0x00,
1950 0x03, 'b', 'a', 'r'
1952 const unsigned char kV3FrameData[] = {
1953 0x80, spdy_version_ch_, 0x00, 0x01,
1954 0x00, 0x00, 0x00, 0x2a,
1955 0x00, 0x00, 0x00, 0x01,
1956 0x00, 0x00, 0x00, 0x00,
1957 kPri, 0x00, 0x00, 0x00,
1958 0x00, 0x02, 0x00, 0x00,
1959 0x00, 0x03, 'b', 'a',
1960 'r', 0x00, 0x00, 0x00,
1961 0x03, 'f', 'o', 'o',
1962 0x00, 0x00, 0x00, 0x03,
1963 'f', 'o', 'o', 0x00,
1964 0x00, 0x00, 0x03, 'b',
1965 'a', 'r'
1967 SpdySynStreamIR syn_stream(1);
1968 syn_stream.set_priority(framer.GetLowestPriority());
1969 syn_stream.SetHeader("bar", "foo");
1970 syn_stream.SetHeader("foo", "bar");
1971 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1972 if (IsSpdy2()) {
1973 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1974 } else if (IsSpdy3()) {
1975 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1976 } else {
1977 LOG(FATAL) << "Unsupported version in test.";
1982 const char kDescription[] =
1983 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1984 "max stream ID";
1986 const unsigned char kV2FrameData[] = {
1987 0x80, spdy_version_ch_, 0x00, 0x01,
1988 0x01, 0x00, 0x00, 0x1D,
1989 0x7f, 0xff, 0xff, 0xff,
1990 0x7f, 0xff, 0xff, 0xff,
1991 0x00, 0x00, 0x00, 0x02,
1992 0x00, 0x00, 0x00, 0x03,
1993 'f', 'o', 'o', 0x00,
1994 0x03, 'f', 'o', 'o',
1995 0x00, 0x03, 'b', 'a',
1998 const unsigned char kV3FrameData[] = {
1999 0x80, spdy_version_ch_, 0x00, 0x01,
2000 0x01, 0x00, 0x00, 0x27,
2001 0x7f, 0xff, 0xff, 0xff,
2002 0x7f, 0xff, 0xff, 0xff,
2003 0x00, 0x00, 0x00, 0x00,
2004 0x00, 0x02, 0x00, 0x00,
2005 0x00, 0x00, 0x00, 0x00,
2006 0x00, 0x03, 'f', 'o',
2007 'o', 0x00, 0x00, 0x00,
2008 0x03, 'f', 'o', 'o',
2009 0x00, 0x00, 0x00, 0x03,
2010 'b', 'a', 'r'
2012 SpdySynStreamIR syn_stream(0x7fffffff);
2013 syn_stream.set_associated_to_stream_id(0x7fffffff);
2014 syn_stream.set_priority(framer.GetHighestPriority());
2015 syn_stream.set_fin(true);
2016 syn_stream.SetHeader("", "foo");
2017 syn_stream.SetHeader("foo", "bar");
2018 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2019 if (IsSpdy2()) {
2020 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2021 } else if (IsSpdy3()) {
2022 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2023 } else {
2024 LOG(FATAL) << "Unsupported version in test.";
2029 const char kDescription[] =
2030 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
2031 "max stream ID";
2033 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
2034 const unsigned char kV2FrameData[] = {
2035 0x80, spdy_version_ch_, 0x00, 0x01,
2036 0x01, 0x00, 0x00, 0x1D,
2037 0x7f, 0xff, 0xff, 0xff,
2038 0x7f, 0xff, 0xff, 0xff,
2039 kPri, 0x00, 0x00, 0x02,
2040 0x00, 0x03, 'b', 'a',
2041 'r', 0x00, 0x03, 'f',
2042 'o', 'o', 0x00, 0x03,
2043 'f', 'o', 'o', 0x00,
2044 0x00
2046 const unsigned char kV3FrameData[] = {
2047 0x80, spdy_version_ch_, 0x00, 0x01,
2048 0x01, 0x00, 0x00, 0x27,
2049 0x7f, 0xff, 0xff, 0xff,
2050 0x7f, 0xff, 0xff, 0xff,
2051 kPri, 0x00, 0x00, 0x00,
2052 0x00, 0x02, 0x00, 0x00,
2053 0x00, 0x03, 'b', 'a',
2054 'r', 0x00, 0x00, 0x00,
2055 0x03, 'f', 'o', 'o',
2056 0x00, 0x00, 0x00, 0x03,
2057 'f', 'o', 'o', 0x00,
2058 0x00, 0x00, 0x00
2060 SpdySynStreamIR syn_stream(0x7fffffff);
2061 syn_stream.set_associated_to_stream_id(0x7fffffff);
2062 syn_stream.set_priority(1);
2063 syn_stream.set_fin(true);
2064 syn_stream.SetHeader("bar", "foo");
2065 syn_stream.SetHeader("foo", "");
2066 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2067 if (IsSpdy2()) {
2068 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2069 } else if (IsSpdy3()) {
2070 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2071 } else {
2072 LOG(FATAL) << "Unsupported version in test.";
2077 // TODO(phajdan.jr): Clean up after we no longer need
2078 // to workaround http://crbug.com/139744.
2079 #if !defined(USE_SYSTEM_ZLIB)
2080 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2081 if (!IsSpdy2() && !IsSpdy3()) {
2082 // SYN_STREAM not supported for SPDY>3
2083 return;
2085 SpdyFramer framer(spdy_version_);
2086 framer.set_enable_compression(true);
2089 const char kDescription[] =
2090 "SYN_STREAM frame, low pri, no FIN";
2091 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2093 const unsigned char kV2FrameData[] = {
2094 0x80, spdy_version_ch_, 0x00, 0x01,
2095 0x00, 0x00, 0x00, 0x36,
2096 0x00, 0x00, 0x00, 0x01,
2097 0x00, 0x00, 0x00, 0x00,
2098 0x80, 0x00, 0x38, 0xea,
2099 0xdf, 0xa2, 0x51, 0xb2,
2100 0x62, 0x60, 0x62, 0x60,
2101 0x4e, 0x4a, 0x2c, 0x62,
2102 0x60, 0x06, 0x08, 0xa0,
2103 0xb4, 0xfc, 0x7c, 0x80,
2104 0x00, 0x62, 0x60, 0x4e,
2105 0xcb, 0xcf, 0x67, 0x60,
2106 0x06, 0x08, 0xa0, 0xa4,
2107 0xc4, 0x22, 0x80, 0x00,
2108 0x02, 0x00, 0x00, 0x00,
2109 0xff, 0xff,
2111 const unsigned char kV3FrameData[] = {
2112 0x80, spdy_version_ch_, 0x00, 0x01,
2113 0x00, 0x00, 0x00, 0x37,
2114 0x00, 0x00, 0x00, 0x01,
2115 0x00, 0x00, 0x00, 0x00,
2116 0x80, 0x00, 0x38, 0xEA,
2117 0xE3, 0xC6, 0xA7, 0xC2,
2118 0x02, 0xE5, 0x0E, 0x50,
2119 0xC2, 0x4B, 0x4A, 0x04,
2120 0xE5, 0x0B, 0x66, 0x80,
2121 0x00, 0x4A, 0xCB, 0xCF,
2122 0x07, 0x08, 0x20, 0x10,
2123 0x95, 0x96, 0x9F, 0x0F,
2124 0xA2, 0x00, 0x02, 0x28,
2125 0x29, 0xB1, 0x08, 0x20,
2126 0x80, 0x00, 0x00, 0x00,
2127 0x00, 0xFF, 0xFF,
2129 const unsigned char kV2SIMDFrameData[] = {
2130 0x80, spdy_version_ch_, 0x00, 0x01,
2131 0x00, 0x00, 0x00, 0x33,
2132 0x00, 0x00, 0x00, 0x01,
2133 0x00, 0x00, 0x00, 0x00,
2134 0x80, 0x00, 0x38, 0xea,
2135 0xdf, 0xa2, 0x51, 0xb2,
2136 0x62, 0x60, 0x62, 0x60,
2137 0x4e, 0x4a, 0x2c, 0x62,
2138 0x60, 0x06, 0x08, 0xa0,
2139 0xb4, 0xfc, 0x7c, 0x80,
2140 0x00, 0x62, 0x60, 0x06,
2141 0x13, 0x00, 0x01, 0x94,
2142 0x94, 0x58, 0x04, 0x10,
2143 0x40, 0x00, 0x00, 0x00,
2144 0x00, 0xff, 0xff,
2146 const unsigned char kV3SIMDFrameData[] = {
2147 0x80, spdy_version_ch_, 0x00, 0x01,
2148 0x00, 0x00, 0x00, 0x32,
2149 0x00, 0x00, 0x00, 0x01,
2150 0x00, 0x00, 0x00, 0x00,
2151 0x80, 0x00, 0x38, 0xea,
2152 0xe3, 0xc6, 0xa7, 0xc2,
2153 0x02, 0xe5, 0x0e, 0x50,
2154 0xc2, 0x4b, 0x4a, 0x04,
2155 0xe5, 0x0b, 0x66, 0x80,
2156 0x00, 0x4a, 0xcb, 0xcf,
2157 0x07, 0x08, 0x20, 0x24,
2158 0x0a, 0x20, 0x80, 0x92,
2159 0x12, 0x8b, 0x00, 0x02,
2160 0x08, 0x00, 0x00, 0x00,
2161 0xff, 0xff,
2164 SpdySynStreamIR syn_stream(1);
2165 syn_stream.set_priority(priority);
2166 syn_stream.SetHeader("bar", "foo");
2167 syn_stream.SetHeader("foo", "bar");
2168 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2169 const unsigned char* frame_data =
2170 reinterpret_cast<const unsigned char*>(frame->data());
2171 if (IsSpdy2()) {
2172 // Try comparing with SIMD version, if that fails, do a failing check
2173 // with pretty printing against non-SIMD version
2174 if (memcmp(frame_data,
2175 kV2SIMDFrameData,
2176 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2177 CompareCharArraysWithHexError(kDescription,
2178 frame_data,
2179 frame->size(),
2180 kV2FrameData,
2181 arraysize(kV2FrameData));
2183 } else if (IsSpdy3()) {
2184 if (memcmp(frame_data,
2185 kV3SIMDFrameData,
2186 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2187 CompareCharArraysWithHexError(kDescription,
2188 frame_data,
2189 frame->size(),
2190 kV3FrameData,
2191 arraysize(kV3FrameData));
2193 } else {
2194 LOG(FATAL) << "Unsupported version in test.";
2198 #endif // !defined(USE_SYSTEM_ZLIB)
2200 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2201 if (spdy_version_ > SPDY3) {
2202 // SYN_REPLY unsupported in SPDY>3
2203 return;
2205 SpdyFramer framer(spdy_version_);
2206 framer.set_enable_compression(false);
2209 const char kDescription[] = "SYN_REPLY frame, no FIN";
2211 const unsigned char kV2FrameData[] = {
2212 0x80, spdy_version_ch_, 0x00, 0x02,
2213 0x00, 0x00, 0x00, 0x1C,
2214 0x00, 0x00, 0x00, 0x01,
2215 0x00, 0x00, 0x00, 0x02,
2216 0x00, 0x03, 'b', 'a',
2217 'r', 0x00, 0x03, 'f',
2218 'o', 'o', 0x00, 0x03,
2219 'f', 'o', 'o', 0x00,
2220 0x03, 'b', 'a', 'r'
2222 const unsigned char kV3FrameData[] = {
2223 0x80, spdy_version_ch_, 0x00, 0x02,
2224 0x00, 0x00, 0x00, 0x24,
2225 0x00, 0x00, 0x00, 0x01,
2226 0x00, 0x00, 0x00, 0x02,
2227 0x00, 0x00, 0x00, 0x03,
2228 'b', 'a', 'r', 0x00,
2229 0x00, 0x00, 0x03, 'f',
2230 'o', 'o', 0x00, 0x00,
2231 0x00, 0x03, 'f', 'o',
2232 'o', 0x00, 0x00, 0x00,
2233 0x03, 'b', 'a', 'r'
2235 SpdySynReplyIR syn_reply(1);
2236 syn_reply.SetHeader("bar", "foo");
2237 syn_reply.SetHeader("foo", "bar");
2238 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2239 if (IsSpdy2()) {
2240 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2241 } else if (IsSpdy3()) {
2242 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2243 } else {
2244 LOG(FATAL) << "Unsupported version in test.";
2249 const char kDescription[] =
2250 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2252 const unsigned char kV2FrameData[] = {
2253 0x80, spdy_version_ch_, 0x00, 0x02,
2254 0x01, 0x00, 0x00, 0x19,
2255 0x7f, 0xff, 0xff, 0xff,
2256 0x00, 0x00, 0x00, 0x02,
2257 0x00, 0x00, 0x00, 0x03,
2258 'f', 'o', 'o', 0x00,
2259 0x03, 'f', 'o', 'o',
2260 0x00, 0x03, 'b', 'a',
2263 const unsigned char kV3FrameData[] = {
2264 0x80, spdy_version_ch_, 0x00, 0x02,
2265 0x01, 0x00, 0x00, 0x21,
2266 0x7f, 0xff, 0xff, 0xff,
2267 0x00, 0x00, 0x00, 0x02,
2268 0x00, 0x00, 0x00, 0x00,
2269 0x00, 0x00, 0x00, 0x03,
2270 'f', 'o', 'o', 0x00,
2271 0x00, 0x00, 0x03, 'f',
2272 'o', 'o', 0x00, 0x00,
2273 0x00, 0x03, 'b', 'a',
2276 SpdySynReplyIR syn_reply(0x7fffffff);
2277 syn_reply.set_fin(true);
2278 syn_reply.SetHeader("", "foo");
2279 syn_reply.SetHeader("foo", "bar");
2280 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2281 if (IsSpdy2()) {
2282 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2283 } else if (IsSpdy3()) {
2284 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2285 } else {
2286 LOG(FATAL) << "Unsupported version in test.";
2291 const char kDescription[] =
2292 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2294 const unsigned char kV2FrameData[] = {
2295 0x80, spdy_version_ch_, 0x00, 0x02,
2296 0x01, 0x00, 0x00, 0x19,
2297 0x7f, 0xff, 0xff, 0xff,
2298 0x00, 0x00, 0x00, 0x02,
2299 0x00, 0x03, 'b', 'a',
2300 'r', 0x00, 0x03, 'f',
2301 'o', 'o', 0x00, 0x03,
2302 'f', 'o', 'o', 0x00,
2303 0x00
2305 const unsigned char kV3FrameData[] = {
2306 0x80, spdy_version_ch_, 0x00, 0x02,
2307 0x01, 0x00, 0x00, 0x21,
2308 0x7f, 0xff, 0xff, 0xff,
2309 0x00, 0x00, 0x00, 0x02,
2310 0x00, 0x00, 0x00, 0x03,
2311 'b', 'a', 'r', 0x00,
2312 0x00, 0x00, 0x03, 'f',
2313 'o', 'o', 0x00, 0x00,
2314 0x00, 0x03, 'f', 'o',
2315 'o', 0x00, 0x00, 0x00,
2316 0x00
2318 SpdySynReplyIR syn_reply(0x7fffffff);
2319 syn_reply.set_fin(true);
2320 syn_reply.SetHeader("bar", "foo");
2321 syn_reply.SetHeader("foo", "");
2322 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2323 if (IsSpdy2()) {
2324 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2325 } else if (IsSpdy3()) {
2326 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2327 } else {
2328 LOG(FATAL) << "Unsupported version in test.";
2333 // TODO(phajdan.jr): Clean up after we no longer need
2334 // to workaround http://crbug.com/139744.
2335 #if !defined(USE_SYSTEM_ZLIB)
2336 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2337 if (spdy_version_ > SPDY3) {
2338 // SYN_REPLY unsupported in SPDY>3
2339 return;
2341 SpdyFramer framer(spdy_version_);
2342 framer.set_enable_compression(true);
2345 const char kDescription[] = "SYN_REPLY frame, no FIN";
2347 const unsigned char kV2FrameData[] = {
2348 0x80, spdy_version_ch_, 0x00, 0x02,
2349 0x00, 0x00, 0x00, 0x32,
2350 0x00, 0x00, 0x00, 0x01,
2351 0x00, 0x00, 0x38, 0xea,
2352 0xdf, 0xa2, 0x51, 0xb2,
2353 0x62, 0x60, 0x62, 0x60,
2354 0x4e, 0x4a, 0x2c, 0x62,
2355 0x60, 0x06, 0x08, 0xa0,
2356 0xb4, 0xfc, 0x7c, 0x80,
2357 0x00, 0x62, 0x60, 0x4e,
2358 0xcb, 0xcf, 0x67, 0x60,
2359 0x06, 0x08, 0xa0, 0xa4,
2360 0xc4, 0x22, 0x80, 0x00,
2361 0x02, 0x00, 0x00, 0x00,
2362 0xff, 0xff,
2364 const unsigned char kV3FrameData[] = {
2365 0x80, spdy_version_ch_, 0x00, 0x02,
2366 0x00, 0x00, 0x00, 0x31,
2367 0x00, 0x00, 0x00, 0x01,
2368 0x38, 0xea, 0xe3, 0xc6,
2369 0xa7, 0xc2, 0x02, 0xe5,
2370 0x0e, 0x50, 0xc2, 0x4b,
2371 0x4a, 0x04, 0xe5, 0x0b,
2372 0x66, 0x80, 0x00, 0x4a,
2373 0xcb, 0xcf, 0x07, 0x08,
2374 0x20, 0x10, 0x95, 0x96,
2375 0x9f, 0x0f, 0xa2, 0x00,
2376 0x02, 0x28, 0x29, 0xb1,
2377 0x08, 0x20, 0x80, 0x00,
2378 0x00, 0x00, 0x00, 0xff,
2379 0xff,
2381 const unsigned char kV2SIMDFrameData[] = {
2382 0x80, spdy_version_ch_, 0x00, 0x02,
2383 0x00, 0x00, 0x00, 0x2f,
2384 0x00, 0x00, 0x00, 0x01,
2385 0x00, 0x00, 0x38, 0xea,
2386 0xdf, 0xa2, 0x51, 0xb2,
2387 0x62, 0x60, 0x62, 0x60,
2388 0x4e, 0x4a, 0x2c, 0x62,
2389 0x60, 0x06, 0x08, 0xa0,
2390 0xb4, 0xfc, 0x7c, 0x80,
2391 0x00, 0x62, 0x60, 0x06,
2392 0x13, 0x00, 0x01, 0x94,
2393 0x94, 0x58, 0x04, 0x10,
2394 0x40, 0x00, 0x00, 0x00,
2395 0x00, 0xff, 0xff,
2397 const unsigned char kV3SIMDFrameData[] = {
2398 0x80, spdy_version_ch_, 0x00, 0x02,
2399 0x00, 0x00, 0x00, 0x2c,
2400 0x00, 0x00, 0x00, 0x01,
2401 0x38, 0xea, 0xe3, 0xc6,
2402 0xa7, 0xc2, 0x02, 0xe5,
2403 0x0e, 0x50, 0xc2, 0x4b,
2404 0x4a, 0x04, 0xe5, 0x0b,
2405 0x66, 0x80, 0x00, 0x4a,
2406 0xcb, 0xcf, 0x07, 0x08,
2407 0x20, 0x24, 0x0a, 0x20,
2408 0x80, 0x92, 0x12, 0x8b,
2409 0x00, 0x02, 0x08, 0x00,
2410 0x00, 0x00, 0xff, 0xff,
2413 SpdySynReplyIR syn_reply(1);
2414 syn_reply.SetHeader("bar", "foo");
2415 syn_reply.SetHeader("foo", "bar");
2416 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2417 const unsigned char* frame_data =
2418 reinterpret_cast<const unsigned char*>(frame->data());
2419 if (IsSpdy2()) {
2420 // Try comparing with SIMD version, if that fails, do a failing check
2421 // with pretty printing against non-SIMD version
2422 if (memcmp(frame_data,
2423 kV2SIMDFrameData,
2424 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2425 CompareCharArraysWithHexError(kDescription,
2426 frame_data,
2427 frame->size(),
2428 kV2FrameData,
2429 arraysize(kV2FrameData));
2431 } else if (IsSpdy3()) {
2432 if (memcmp(frame_data,
2433 kV3SIMDFrameData,
2434 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2435 CompareCharArraysWithHexError(kDescription,
2436 frame_data,
2437 frame->size(),
2438 kV3FrameData,
2439 arraysize(kV3FrameData));
2441 } else {
2442 LOG(FATAL) << "Unsupported version in test.";
2446 #endif // !defined(USE_SYSTEM_ZLIB)
2448 TEST_P(SpdyFramerTest, CreateRstStream) {
2449 SpdyFramer framer(spdy_version_);
2452 const char kDescription[] = "RST_STREAM frame";
2453 const unsigned char kV3FrameData[] = { // Also applies for V2.
2454 0x80, spdy_version_ch_, 0x00, 0x03,
2455 0x00, 0x00, 0x00, 0x08,
2456 0x00, 0x00, 0x00, 0x01,
2457 0x00, 0x00, 0x00, 0x01,
2459 const unsigned char kH2FrameData[] = {
2460 0x00, 0x00, 0x07, 0x03,
2461 0x00, 0x00, 0x00, 0x00,
2462 0x01, 0x00, 0x00, 0x00,
2463 0x01, 0x52, 0x53, 0x54
2465 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2466 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2467 if (IsHttp2()) {
2468 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2469 } else {
2470 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2475 const char kDescription[] = "RST_STREAM frame with max stream ID";
2476 const unsigned char kV3FrameData[] = { // Also applies for V2.
2477 0x80, spdy_version_ch_, 0x00, 0x03,
2478 0x00, 0x00, 0x00, 0x08,
2479 0x7f, 0xff, 0xff, 0xff,
2480 0x00, 0x00, 0x00, 0x01,
2482 const unsigned char kH2FrameData[] = {
2483 0x00, 0x00, 0x04, 0x03,
2484 0x00, 0x7f, 0xff, 0xff,
2485 0xff, 0x00, 0x00, 0x00,
2486 0x01,
2488 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2489 RST_STREAM_PROTOCOL_ERROR,
2490 "");
2491 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2492 if (IsHttp2()) {
2493 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2494 } else {
2495 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2500 const char kDescription[] = "RST_STREAM frame with max status code";
2501 const unsigned char kV3FrameData[] = { // Also applies for V2.
2502 0x80, spdy_version_ch_, 0x00, 0x03,
2503 0x00, 0x00, 0x00, 0x08,
2504 0x7f, 0xff, 0xff, 0xff,
2505 0x00, 0x00, 0x00, 0x06,
2507 const unsigned char kH2FrameData[] = {
2508 0x00, 0x00, 0x04, 0x03,
2509 0x00, 0x7f, 0xff, 0xff,
2510 0xff, 0x00, 0x00, 0x00,
2511 0x02,
2513 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2514 RST_STREAM_INTERNAL_ERROR,
2515 "");
2516 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2517 if (IsHttp2()) {
2518 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2519 } else {
2520 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2525 TEST_P(SpdyFramerTest, CreateSettings) {
2526 SpdyFramer framer(spdy_version_);
2529 const char kDescription[] = "Network byte order SETTINGS frame";
2531 const unsigned char kV2FrameData[] = {
2532 0x80, spdy_version_ch_, 0x00, 0x04,
2533 0x00, 0x00, 0x00, 0x0c,
2534 0x00, 0x00, 0x00, 0x01,
2535 0x07, 0x00, 0x00, 0x01,
2536 0x0a, 0x0b, 0x0c, 0x0d,
2538 const unsigned char kV3FrameData[] = {
2539 0x80, spdy_version_ch_, 0x00, 0x04,
2540 0x00, 0x00, 0x00, 0x0c,
2541 0x00, 0x00, 0x00, 0x01,
2542 0x01, 0x00, 0x00, 0x07,
2543 0x0a, 0x0b, 0x0c, 0x0d,
2545 const unsigned char kH2FrameData[] = {
2546 0x00, 0x00, 0x06, 0x04,
2547 0x00, 0x00, 0x00, 0x00,
2548 0x00, 0x00, 0x04, 0x0a,
2549 0x0b, 0x0c, 0x0d,
2552 uint32 kValue = 0x0a0b0c0d;
2553 SpdySettingsIR settings_ir;
2555 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2556 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2557 settings_ir.AddSetting(kId,
2558 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2559 kFlags & SETTINGS_FLAG_PERSISTED,
2560 kValue);
2562 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2563 if (IsSpdy2()) {
2564 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2565 } else if (IsSpdy3()) {
2566 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2567 } else {
2568 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2573 const char kDescription[] = "Basic SETTINGS frame";
2575 const unsigned char kV2FrameData[] = {
2576 0x80, spdy_version_ch_, 0x00, 0x04,
2577 0x00, 0x00, 0x00, 0x24,
2578 0x00, 0x00, 0x00, 0x04,
2579 0x01, 0x00, 0x00, 0x00, // 1st Setting
2580 0x00, 0x00, 0x00, 0x05,
2581 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2582 0x00, 0x00, 0x00, 0x06,
2583 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2584 0x00, 0x00, 0x00, 0x07,
2585 0x04, 0x00, 0x00, 0x00, // 4th Setting
2586 0x00, 0x00, 0x00, 0x08,
2588 const unsigned char kV3FrameData[] = {
2589 0x80, spdy_version_ch_, 0x00, 0x04,
2590 0x00, 0x00, 0x00, 0x24,
2591 0x00, 0x00, 0x00, 0x04,
2592 0x00, 0x00, 0x00, 0x01, // 1st Setting
2593 0x00, 0x00, 0x00, 0x05,
2594 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2595 0x00, 0x00, 0x00, 0x06,
2596 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2597 0x00, 0x00, 0x00, 0x07,
2598 0x00, 0x00, 0x00, 0x04, // 4th Setting
2599 0x00, 0x00, 0x00, 0x08,
2601 // These end up seemingly out of order because of the way that our internal
2602 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2603 // the wire.
2604 const unsigned char kH2FrameData[] = {
2605 0x00, 0x00, 0x18, 0x04,
2606 0x00, 0x00, 0x00, 0x00,
2607 0x00, 0x00, 0x03, // 3rd Setting
2608 0x00, 0x00, 0x00, 0x07,
2609 0x00, 0x04, // 4th Setting
2610 0x00, 0x00, 0x00, 0x08,
2611 0x00, 0x01, // 1st Setting
2612 0x00, 0x00, 0x00, 0x05,
2613 0x00, 0x02, // 2nd Setting
2614 0x00, 0x00, 0x00, 0x06,
2617 SpdySettingsIR settings_ir;
2618 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2619 false, // persist
2620 false, // persisted
2622 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2623 false, // persist
2624 false, // persisted
2626 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2627 false, // persist
2628 false, // persisted
2630 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2631 false, // persist
2632 false, // persisted
2634 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2636 if (IsSpdy2()) {
2637 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2638 } else if (IsSpdy3()) {
2639 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2640 } else {
2641 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2646 const char kDescription[] = "Empty SETTINGS frame";
2648 const unsigned char kV3FrameData[] = { // Also applies for V2.
2649 0x80, spdy_version_ch_, 0x00, 0x04,
2650 0x00, 0x00, 0x00, 0x04,
2651 0x00, 0x00, 0x00, 0x00,
2653 const unsigned char kH2FrameData[] = {
2654 0x00, 0x00, 0x00, 0x04,
2655 0x00, 0x00, 0x00, 0x00,
2656 0x00,
2658 SpdySettingsIR settings_ir;
2659 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2660 if (IsHttp2()) {
2661 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2662 } else {
2663 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2668 TEST_P(SpdyFramerTest, CreatePingFrame) {
2669 SpdyFramer framer(spdy_version_);
2672 const char kDescription[] = "PING frame";
2673 const unsigned char kV3FrameData[] = { // Also applies for V2.
2674 0x80, spdy_version_ch_, 0x00, 0x06,
2675 0x00, 0x00, 0x00, 0x04,
2676 0x12, 0x34, 0x56, 0x78,
2678 const unsigned char kH2FrameData[] = {
2679 0x00, 0x00, 0x08, 0x06,
2680 0x00, 0x00, 0x00, 0x00,
2681 0x00, 0x12, 0x34, 0x56,
2682 0x78, 0x9a, 0xbc, 0xde,
2683 0xff,
2685 const unsigned char kH2FrameDataWithAck[] = {
2686 0x00, 0x00, 0x08, 0x06,
2687 0x01, 0x00, 0x00, 0x00,
2688 0x00, 0x12, 0x34, 0x56,
2689 0x78, 0x9a, 0xbc, 0xde,
2690 0xff,
2692 scoped_ptr<SpdyFrame> frame;
2693 if (IsHttp2()) {
2694 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2695 SpdyPingIR ping_ir(kPingId);
2696 // Tests SpdyPingIR when the ping is not an ack.
2697 ASSERT_FALSE(ping_ir.is_ack());
2698 frame.reset(framer.SerializePing(ping_ir));
2699 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2701 // Tests SpdyPingIR when the ping is an ack.
2702 ping_ir.set_is_ack(true);
2703 frame.reset(framer.SerializePing(ping_ir));
2704 CompareFrame(kDescription, *frame, kH2FrameDataWithAck,
2705 arraysize(kH2FrameDataWithAck));
2707 } else {
2708 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2709 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2714 TEST_P(SpdyFramerTest, CreateGoAway) {
2715 SpdyFramer framer(spdy_version_);
2718 const char kDescription[] = "GOAWAY frame";
2719 const unsigned char kV2FrameData[] = {
2720 0x80, spdy_version_ch_, 0x00, 0x07,
2721 0x00, 0x00, 0x00, 0x04,
2722 0x00, 0x00, 0x00, 0x00, // Stream Id
2724 const unsigned char kV3FrameData[] = {
2725 0x80, spdy_version_ch_, 0x00, 0x07,
2726 0x00, 0x00, 0x00, 0x08,
2727 0x00, 0x00, 0x00, 0x00, // Stream Id
2728 0x00, 0x00, 0x00, 0x00, // Status
2730 const unsigned char kH2FrameData[] = {
2731 0x00, 0x00, 0x0a, 0x07,
2732 0x00, 0x00, 0x00, 0x00,
2733 0x00, 0x00, 0x00, 0x00, // Stream id
2734 0x00, 0x00, 0x00, 0x00, // Status
2735 0x00, 0x47, 0x41, // Opaque Description
2737 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2738 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2739 if (IsSpdy2()) {
2740 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2741 } else if (IsSpdy3()) {
2742 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2743 } else {
2744 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2749 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2750 const unsigned char kV2FrameData[] = {
2751 0x80, spdy_version_ch_, 0x00, 0x07,
2752 0x00, 0x00, 0x00, 0x04,
2753 0x7f, 0xff, 0xff, 0xff, // Stream Id
2755 const unsigned char kV3FrameData[] = {
2756 0x80, spdy_version_ch_, 0x00, 0x07,
2757 0x00, 0x00, 0x00, 0x08,
2758 0x7f, 0xff, 0xff, 0xff, // Stream Id
2759 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2761 const unsigned char kH2FrameData[] = {
2762 0x00, 0x00, 0x0a, 0x07,
2763 0x00, 0x00, 0x00, 0x00,
2764 0x00, 0x7f, 0xff, 0xff, // Stream Id
2765 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2766 0x02, 0x47, 0x41, // Opaque Description
2768 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2769 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2770 if (IsSpdy2()) {
2771 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2772 } else if (IsSpdy3()) {
2773 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2774 } else {
2775 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2780 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2781 SpdyFramer framer(spdy_version_);
2782 framer.set_enable_compression(false);
2785 const char kDescription[] = "HEADERS frame, no FIN";
2787 const unsigned char kV2FrameData[] = {
2788 0x80, spdy_version_ch_, 0x00, 0x08,
2789 0x00, 0x00, 0x00, 0x1C,
2790 0x00, 0x00, 0x00, 0x01,
2791 0x00, 0x00, 0x00, 0x02,
2792 0x00, 0x03, 'b', 'a',
2793 'r', 0x00, 0x03, 'f',
2794 'o', 'o', 0x00, 0x03,
2795 'f', 'o', 'o', 0x00,
2796 0x03, 'b', 'a', 'r'
2798 const unsigned char kV3FrameData[] = {
2799 0x80, spdy_version_ch_, 0x00, 0x08,
2800 0x00, 0x00, 0x00, 0x24,
2801 0x00, 0x00, 0x00, 0x01,
2802 0x00, 0x00, 0x00, 0x02,
2803 0x00, 0x00, 0x00, 0x03,
2804 'b', 'a', 'r', 0x00,
2805 0x00, 0x00, 0x03, 'f',
2806 'o', 'o', 0x00, 0x00,
2807 0x00, 0x03, 'f', 'o',
2808 'o', 0x00, 0x00, 0x00,
2809 0x03, 'b', 'a', 'r'
2811 const unsigned char kH2FrameData[] = {
2812 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2813 0x04, 0x00, 0x00, 0x00, // Stream 1
2814 0x01, 0x00, 0x03, 0x62, // @.ba
2815 0x61, 0x72, 0x03, 0x66, // r.fo
2816 0x6f, 0x6f, 0x00, 0x03, // o@.f
2817 0x66, 0x6f, 0x6f, 0x03, // oo.b
2818 0x62, 0x61, 0x72, // ar
2820 SpdyHeadersIR headers_ir(1);
2821 headers_ir.SetHeader("bar", "foo");
2822 headers_ir.SetHeader("foo", "bar");
2823 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2824 if (IsSpdy2()) {
2825 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2826 } else if (IsSpdy3()) {
2827 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2828 } else {
2829 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2834 const char kDescription[] =
2835 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2837 const unsigned char kV2FrameData[] = {
2838 0x80, spdy_version_ch_, 0x00, 0x08,
2839 0x01, 0x00, 0x00, 0x19,
2840 0x7f, 0xff, 0xff, 0xff,
2841 0x00, 0x00, 0x00, 0x02,
2842 0x00, 0x00, 0x00, 0x03,
2843 'f', 'o', 'o', 0x00,
2844 0x03, 'f', 'o', 'o',
2845 0x00, 0x03, 'b', 'a',
2848 const unsigned char kV3FrameData[] = {
2849 0x80, spdy_version_ch_, 0x00, 0x08,
2850 0x01, 0x00, 0x00, 0x21,
2851 0x7f, 0xff, 0xff, 0xff,
2852 0x00, 0x00, 0x00, 0x02,
2853 0x00, 0x00, 0x00, 0x00,
2854 0x00, 0x00, 0x00, 0x03,
2855 'f', 'o', 'o', 0x00,
2856 0x00, 0x00, 0x03, 'f',
2857 'o', 'o', 0x00, 0x00,
2858 0x00, 0x03, 'b', 'a',
2861 const unsigned char kH2FrameData[] = {
2862 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2863 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2864 0xff, 0x00, 0x00, 0x03, // @..
2865 0x66, 0x6f, 0x6f, 0x00, // foo@
2866 0x03, 0x66, 0x6f, 0x6f, // .foo
2867 0x03, 0x62, 0x61, 0x72, // .bar
2869 SpdyHeadersIR headers_ir(0x7fffffff);
2870 headers_ir.set_fin(true);
2871 headers_ir.SetHeader("", "foo");
2872 headers_ir.SetHeader("foo", "bar");
2873 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2874 if (IsSpdy2()) {
2875 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2876 } else if (IsSpdy3()) {
2877 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2878 } else {
2879 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2884 const char kDescription[] =
2885 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2887 const unsigned char kV2FrameData[] = {
2888 0x80, spdy_version_ch_, 0x00, 0x08,
2889 0x01, 0x00, 0x00, 0x19,
2890 0x7f, 0xff, 0xff, 0xff,
2891 0x00, 0x00, 0x00, 0x02,
2892 0x00, 0x03, 'b', 'a',
2893 'r', 0x00, 0x03, 'f',
2894 'o', 'o', 0x00, 0x03,
2895 'f', 'o', 'o', 0x00,
2896 0x00
2898 const unsigned char kV3FrameData[] = {
2899 0x80, spdy_version_ch_, 0x00, 0x08,
2900 0x01, 0x00, 0x00, 0x21,
2901 0x7f, 0xff, 0xff, 0xff,
2902 0x00, 0x00, 0x00, 0x02,
2903 0x00, 0x00, 0x00, 0x03,
2904 'b', 'a', 'r', 0x00,
2905 0x00, 0x00, 0x03, 'f',
2906 'o', 'o', 0x00, 0x00,
2907 0x00, 0x03, 'f', 'o',
2908 'o', 0x00, 0x00, 0x00,
2909 0x00
2911 const unsigned char kH2FrameData[] = {
2912 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2913 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2914 0xff, 0x00, 0x03, 0x62, // @.b
2915 0x61, 0x72, 0x03, 0x66, // ar.f
2916 0x6f, 0x6f, 0x00, 0x03, // oo@.
2917 0x66, 0x6f, 0x6f, 0x00, // foo.
2919 SpdyHeadersIR headers_ir(0x7fffffff);
2920 headers_ir.set_fin(true);
2921 headers_ir.SetHeader("bar", "foo");
2922 headers_ir.SetHeader("foo", "");
2923 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2924 if (IsSpdy2()) {
2925 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2926 } else if (IsSpdy3()) {
2927 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2928 } else {
2929 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2934 const char kDescription[] =
2935 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2937 const unsigned char kH2FrameData[] = {
2938 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2939 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2940 0xff, 0x00, 0x00, 0x00, // exclusive, parent stream
2941 0x00, 0xdb, // weight
2942 0x00, 0x03, 0x62, 0x61, // @.ba
2943 0x72, 0x03, 0x66, 0x6f, // r.fo
2944 0x6f, 0x00, 0x03, 0x66, // o@.f
2945 0x6f, 0x6f, 0x00, // oo.
2947 SpdyHeadersIR headers_ir(0x7fffffff);
2948 headers_ir.set_fin(true);
2949 headers_ir.set_priority(1);
2950 headers_ir.set_has_priority(true);
2951 headers_ir.SetHeader("bar", "foo");
2952 headers_ir.SetHeader("foo", "");
2953 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2954 if (IsSpdy2() || IsSpdy3()) {
2955 // HEADERS with priority not supported.
2956 } else {
2957 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2962 const char kDescription[] =
2963 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2964 "exclusive=true, parent_stream=0";
2966 const unsigned char kH2FrameData[] = {
2967 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2968 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2969 0xff, 0x80, 0x00, 0x00, // exclusive, parent stream
2970 0x00, 0xdb, // weight
2971 0x00, 0x03, 0x62, 0x61, // @.ba
2972 0x72, 0x03, 0x66, 0x6f, // r.fo
2973 0x6f, 0x00, 0x03, 0x66, // o@.f
2974 0x6f, 0x6f, 0x00, // oo.
2976 SpdyHeadersIR headers_ir(0x7fffffff);
2977 headers_ir.set_fin(true);
2978 headers_ir.set_priority(1);
2979 headers_ir.set_has_priority(true);
2980 headers_ir.set_exclusive(true);
2981 headers_ir.set_parent_stream_id(0);
2982 headers_ir.SetHeader("bar", "foo");
2983 headers_ir.SetHeader("foo", "");
2984 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2985 if (IsSpdy2() || IsSpdy3()) {
2986 // HEADERS with priority not supported.
2987 } else {
2988 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2993 const char kDescription[] =
2994 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2995 "exclusive=false, parent_stream=max stream ID";
2997 const unsigned char kH2FrameData[] = {
2998 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2999 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
3000 0xff, 0x7f, 0xff, 0xff, // exclusive, parent stream
3001 0xff, 0xdb, // weight
3002 0x00, 0x03, 0x62, 0x61, // @.ba
3003 0x72, 0x03, 0x66, 0x6f, // r.fo
3004 0x6f, 0x00, 0x03, 0x66, // o@.f
3005 0x6f, 0x6f, 0x00, // oo.
3007 SpdyHeadersIR headers_ir(0x7fffffff);
3008 headers_ir.set_fin(true);
3009 headers_ir.set_priority(1);
3010 headers_ir.set_has_priority(true);
3011 headers_ir.set_exclusive(false);
3012 headers_ir.set_parent_stream_id(0x7fffffff);
3013 headers_ir.SetHeader("bar", "foo");
3014 headers_ir.SetHeader("foo", "");
3015 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3016 if (IsSpdy2() || IsSpdy3()) {
3017 // HEADERS with priority not supported.
3018 } else {
3019 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3024 const char kDescription[] =
3025 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
3027 const unsigned char kH2FrameData[] = {
3028 0x00, 0x00, 0x15, 0x01, // Headers
3029 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
3030 // 0x7fffffff
3031 0xff, 0x05, 0x00, 0x00, // Pad length field
3032 0x03, 0x66, 0x6f, 0x6f, // .foo
3033 0x00, 0x03, 0x66, 0x6f, // @.fo
3034 0x6f, 0x03, 0x62, 0x61, // o.ba
3035 0x72, // r
3036 // Padding payload
3037 0x00, 0x00, 0x00, 0x00, 0x00,
3039 SpdyHeadersIR headers_ir(0x7fffffff);
3040 headers_ir.set_fin(true);
3041 headers_ir.SetHeader("", "foo");
3042 headers_ir.SetHeader("foo", "bar");
3043 headers_ir.set_padding_len(6);
3044 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3045 if (IsSpdy2() || IsSpdy3()) {
3046 // Padding is not supported.
3047 } else {
3048 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3053 // TODO(phajdan.jr): Clean up after we no longer need
3054 // to workaround http://crbug.com/139744.
3055 #if !defined(USE_SYSTEM_ZLIB)
3056 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
3057 SpdyFramer framer(spdy_version_);
3058 framer.set_enable_compression(true);
3061 const char kDescription[] = "HEADERS frame, no FIN";
3063 const unsigned char kV2FrameData[] = {
3064 0x80, spdy_version_ch_, 0x00, 0x08,
3065 0x00, 0x00, 0x00, 0x32,
3066 0x00, 0x00, 0x00, 0x01,
3067 0x00, 0x00, 0x38, 0xea,
3068 0xdf, 0xa2, 0x51, 0xb2,
3069 0x62, 0x60, 0x62, 0x60,
3070 0x4e, 0x4a, 0x2c, 0x62,
3071 0x60, 0x06, 0x08, 0xa0,
3072 0xb4, 0xfc, 0x7c, 0x80,
3073 0x00, 0x62, 0x60, 0x4e,
3074 0xcb, 0xcf, 0x67, 0x60,
3075 0x06, 0x08, 0xa0, 0xa4,
3076 0xc4, 0x22, 0x80, 0x00,
3077 0x02, 0x00, 0x00, 0x00,
3078 0xff, 0xff,
3080 const unsigned char kV3FrameData[] = {
3081 0x80, spdy_version_ch_, 0x00, 0x08,
3082 0x00, 0x00, 0x00, 0x31,
3083 0x00, 0x00, 0x00, 0x01,
3084 0x38, 0xea, 0xe3, 0xc6,
3085 0xa7, 0xc2, 0x02, 0xe5,
3086 0x0e, 0x50, 0xc2, 0x4b,
3087 0x4a, 0x04, 0xe5, 0x0b,
3088 0x66, 0x80, 0x00, 0x4a,
3089 0xcb, 0xcf, 0x07, 0x08,
3090 0x20, 0x10, 0x95, 0x96,
3091 0x9f, 0x0f, 0xa2, 0x00,
3092 0x02, 0x28, 0x29, 0xb1,
3093 0x08, 0x20, 0x80, 0x00,
3094 0x00, 0x00, 0x00, 0xff,
3095 0xff,
3097 const unsigned char kV2SIMDFrameData[] = {
3098 0x80, spdy_version_ch_, 0x00, 0x08,
3099 0x00, 0x00, 0x00, 0x2f,
3100 0x00, 0x00, 0x00, 0x01,
3101 0x00, 0x00, 0x38, 0xea,
3102 0xdf, 0xa2, 0x51, 0xb2,
3103 0x62, 0x60, 0x62, 0x60,
3104 0x4e, 0x4a, 0x2c, 0x62,
3105 0x60, 0x06, 0x08, 0xa0,
3106 0xb4, 0xfc, 0x7c, 0x80,
3107 0x00, 0x62, 0x60, 0x06,
3108 0x13, 0x00, 0x01, 0x94,
3109 0x94, 0x58, 0x04, 0x10,
3110 0x40, 0x00, 0x00, 0x00,
3111 0x00, 0xff, 0xff,
3113 const unsigned char kV3SIMDFrameData[] = {
3114 0x80, spdy_version_ch_, 0x00, 0x08,
3115 0x00, 0x00, 0x00, 0x2c,
3116 0x00, 0x00, 0x00, 0x01,
3117 0x38, 0xea, 0xe3, 0xc6,
3118 0xa7, 0xc2, 0x02, 0xe5,
3119 0x0e, 0x50, 0xc2, 0x4b,
3120 0x4a, 0x04, 0xe5, 0x0b,
3121 0x66, 0x80, 0x00, 0x4a,
3122 0xcb, 0xcf, 0x07, 0x08,
3123 0x20, 0x24, 0x0a, 0x20,
3124 0x80, 0x92, 0x12, 0x8b,
3125 0x00, 0x02, 0x08, 0x00,
3126 0x00, 0x00, 0xff, 0xff,
3129 SpdyHeadersIR headers_ir(1);
3130 headers_ir.SetHeader("bar", "foo");
3131 headers_ir.SetHeader("foo", "bar");
3132 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3133 const unsigned char* frame_data =
3134 reinterpret_cast<const unsigned char*>(frame->data());
3135 if (IsSpdy2()) {
3136 // Try comparing with SIMD version, if that fails, do a failing check
3137 // with pretty printing against non-SIMD version
3138 if (memcmp(frame_data,
3139 kV2SIMDFrameData,
3140 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3141 CompareCharArraysWithHexError(kDescription,
3142 frame_data,
3143 frame->size(),
3144 kV2FrameData,
3145 arraysize(kV2FrameData));
3147 } else if (IsSpdy3()) {
3148 if (memcmp(frame_data,
3149 kV3SIMDFrameData,
3150 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3151 CompareCharArraysWithHexError(kDescription,
3152 frame_data,
3153 frame->size(),
3154 kV3FrameData,
3155 arraysize(kV3FrameData));
3157 } else {
3158 // Deflate compression doesn't apply to HPACK.
3162 #endif // !defined(USE_SYSTEM_ZLIB)
3164 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3165 SpdyFramer framer(spdy_version_);
3168 const char kDescription[] = "WINDOW_UPDATE frame";
3169 const unsigned char kV3FrameData[] = { // Also applies for V2.
3170 0x80, spdy_version_ch_, 0x00, 0x09,
3171 0x00, 0x00, 0x00, 0x08,
3172 0x00, 0x00, 0x00, 0x01,
3173 0x00, 0x00, 0x00, 0x01,
3175 const unsigned char kH2FrameData[] = {
3176 0x00, 0x00, 0x04, 0x08,
3177 0x00, 0x00, 0x00, 0x00,
3178 0x01, 0x00, 0x00, 0x00,
3179 0x01,
3181 scoped_ptr<SpdyFrame> frame(
3182 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3183 if (IsHttp2()) {
3184 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3185 } else {
3186 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3191 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3192 const unsigned char kV3FrameData[] = { // Also applies for V2.
3193 0x80, spdy_version_ch_, 0x00, 0x09,
3194 0x00, 0x00, 0x00, 0x08,
3195 0x7f, 0xff, 0xff, 0xff,
3196 0x00, 0x00, 0x00, 0x01,
3198 const unsigned char kH2FrameData[] = {
3199 0x00, 0x00, 0x04, 0x08,
3200 0x00, 0x7f, 0xff, 0xff,
3201 0xff, 0x00, 0x00, 0x00,
3202 0x01,
3204 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3205 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3206 if (IsHttp2()) {
3207 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3208 } else {
3209 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3214 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3215 const unsigned char kV3FrameData[] = { // Also applies for V2.
3216 0x80, spdy_version_ch_, 0x00, 0x09,
3217 0x00, 0x00, 0x00, 0x08,
3218 0x00, 0x00, 0x00, 0x01,
3219 0x7f, 0xff, 0xff, 0xff,
3221 const unsigned char kH2FrameData[] = {
3222 0x00, 0x00, 0x04, 0x08,
3223 0x00, 0x00, 0x00, 0x00,
3224 0x01, 0x7f, 0xff, 0xff,
3225 0xff,
3227 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3228 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3229 if (IsHttp2()) {
3230 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3231 } else {
3232 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3237 TEST_P(SpdyFramerTest, SerializeBlocked) {
3238 if (spdy_version_ <= SPDY3) {
3239 return;
3242 SpdyFramer framer(spdy_version_);
3244 const char kDescription[] = "BLOCKED frame";
3245 const unsigned char kType = static_cast<unsigned char>(
3246 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3247 const unsigned char kFrameData[] = {
3248 0x00, 0x00, 0x00, kType, 0x00,
3249 0x00, 0x00, 0x00, 0x00,
3251 SpdyBlockedIR blocked_ir(0);
3252 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3253 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3256 TEST_P(SpdyFramerTest, CreateBlocked) {
3257 if (spdy_version_ <= SPDY3) {
3258 return;
3261 SpdyFramer framer(spdy_version_);
3263 const char kDescription[] = "BLOCKED frame";
3264 const SpdyStreamId kStreamId = 3;
3266 scoped_ptr<SpdySerializedFrame> frame_serialized(
3267 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3268 SpdyBlockedIR blocked_ir(kStreamId);
3269 scoped_ptr<SpdySerializedFrame> frame_created(
3270 framer.SerializeFrame(blocked_ir));
3272 CompareFrames(kDescription, *frame_serialized, *frame_created);
3275 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3276 if (spdy_version_ <= SPDY3) {
3277 return;
3281 // Test framing PUSH_PROMISE without padding.
3282 SpdyFramer framer(spdy_version_);
3283 framer.set_enable_compression(false);
3284 const char kDescription[] = "PUSH_PROMISE frame without padding";
3286 const unsigned char kFrameData[] = {
3287 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3288 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3289 0x2a, 0x00, 0x00, 0x00, // Stream 42
3290 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3291 0x61, 0x72, 0x03, 0x66, // ar.f
3292 0x6f, 0x6f, 0x00, 0x03, // oo@.
3293 0x66, 0x6f, 0x6f, 0x03, // foo.
3294 0x62, 0x61, 0x72, // bar
3297 SpdyPushPromiseIR push_promise(42, 57);
3298 push_promise.SetHeader("bar", "foo");
3299 push_promise.SetHeader("foo", "bar");
3300 scoped_ptr<SpdySerializedFrame> frame(
3301 framer.SerializePushPromise(push_promise));
3302 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3306 // Test framing PUSH_PROMISE with one byte of padding.
3307 SpdyFramer framer(spdy_version_);
3308 framer.set_enable_compression(false);
3309 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3311 const unsigned char kFrameData[] = {
3312 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3313 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3314 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3315 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3316 0x62, 0x61, 0x72, 0x03, // bar.
3317 0x66, 0x6f, 0x6f, 0x00, // foo@
3318 0x03, 0x66, 0x6f, 0x6f, // .foo
3319 0x03, 0x62, 0x61, 0x72, // .bar
3322 SpdyPushPromiseIR push_promise(42, 57);
3323 push_promise.set_padding_len(1);
3324 push_promise.SetHeader("bar", "foo");
3325 push_promise.SetHeader("foo", "bar");
3326 scoped_ptr<SpdySerializedFrame> frame(
3327 framer.SerializePushPromise(push_promise));
3328 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3332 // Test framing PUSH_PROMISE with 177 bytes of padding.
3333 SpdyFramer framer(spdy_version_);
3334 framer.set_enable_compression(false);
3335 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3337 const unsigned char kFrameData[] = {
3338 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3339 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3340 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3341 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3342 0x62, 0x61, 0x72, 0x03, // bar.
3343 0x66, 0x6f, 0x6f, 0x00, // foo@
3344 0x03, 0x66, 0x6f, 0x6f, // .foo
3345 0x03, 0x62, 0x61, 0x72, // .bar
3346 // Padding of 176 0x00(s).
3347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
3364 SpdyPushPromiseIR push_promise(42, 57);
3365 push_promise.set_padding_len(177);
3366 push_promise.SetHeader("bar", "foo");
3367 push_promise.SetHeader("foo", "bar");
3368 scoped_ptr<SpdySerializedFrame> frame(
3369 framer.SerializePushPromise(push_promise));
3370 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3374 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
3375 if (spdy_version_ <= SPDY3) {
3376 return;
3379 SpdyFramer framer(spdy_version_);
3380 // Test case from https://crbug.com/464748.
3381 EXPECT_EQ(1u,
3382 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2039));
3383 EXPECT_EQ(2u,
3384 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2040));
3387 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3388 if (spdy_version_ <= SPDY3) {
3389 return;
3392 SpdyFramer framer(spdy_version_);
3393 framer.set_enable_compression(false);
3394 const char kDescription[] = "CONTINUATION frame";
3396 const unsigned char kFrameData[] = {
3397 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3398 0x04, 0x00, 0x00, 0x00, // end_headers = true
3399 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3400 0x61, 0x72, 0x03, 0x66, // ar.f
3401 0x6f, 0x6f, 0x00, 0x03, // oo@.
3402 0x66, 0x6f, 0x6f, 0x03, // foo.
3403 0x62, 0x61, 0x72, // bar
3406 SpdyContinuationIR continuation(42);
3407 continuation.SetHeader("bar", "foo");
3408 continuation.SetHeader("foo", "bar");
3409 continuation.set_end_headers(true);
3410 scoped_ptr<SpdySerializedFrame> frame(
3411 framer.SerializeContinuation(continuation));
3412 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3415 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3416 if (spdy_version_ <= SPDY3) {
3417 return;
3421 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3422 // padding, cannot hold all the data payload, which is overflowed to the
3423 // consecutive CONTINUATION frame.
3424 SpdyFramer framer(spdy_version_);
3425 framer.set_enable_compression(false);
3426 const char kDescription[] =
3427 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3429 const unsigned char kPartialPushPromiseFrameData[] = {
3430 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3431 0x08, 0x00, 0x00, 0x00, // PADDED
3432 0x2a, 0x00, 0x00, 0x00, // Stream 42
3433 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3434 0x78, 0x78, 0x78, 0x7f, // xxx.
3435 0x81, 0x07, 0x78, 0x78, // ..xx
3436 0x78, 0x78, 0x78, 0x78, // xxxx
3437 0x78, 0x78, 0x78, 0x78, // xxxx
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, // xx
3459 const unsigned char kContinuationFrameData[] = {
3460 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3461 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3462 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3463 0x78, 0x78, 0x78, 0x78, // xxxx
3464 0x78, 0x78, 0x78, 0x78, // xxxx
3465 0x78, 0x78, 0x78, 0x78, // xxxx
3466 0x78, 0x78, 0x78, 0x78, // xxxx
3467 0x78, 0x78,
3470 SpdyPushPromiseIR push_promise(42, 57);
3471 push_promise.set_padding_len(1);
3472 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3473 push_promise.SetHeader("xxx", big_value);
3474 scoped_ptr<SpdySerializedFrame> frame(
3475 framer.SerializePushPromise(push_promise));
3477 // The entire frame should look like below:
3478 // Name Length in Byte
3479 // ------------------------------------------- Begin of PUSH_PROMISE frame
3480 // PUSH_PROMISE header 9
3481 // Pad length field 1
3482 // Promised stream 4
3483 // Length field of key 2
3484 // Content of key 3
3485 // Length field of value 3
3486 // Part of big_value 16361
3487 // ------------------------------------------- Begin of CONTINUATION frame
3488 // CONTINUATION header 9
3489 // Remaining of big_value 22
3490 // ------------------------------------------- End
3492 // Length of everything listed above except big_value.
3493 int len_non_data_payload = 31;
3494 EXPECT_EQ(
3495 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3496 frame->size());
3498 // Partially compare the PUSH_PROMISE frame against the template.
3499 const unsigned char* frame_data =
3500 reinterpret_cast<const unsigned char*>(frame->data());
3501 CompareCharArraysWithHexError(kDescription,
3502 frame_data,
3503 arraysize(kPartialPushPromiseFrameData),
3504 kPartialPushPromiseFrameData,
3505 arraysize(kPartialPushPromiseFrameData));
3507 // Compare the CONTINUATION frame against the template.
3508 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3509 CompareCharArraysWithHexError(kDescription,
3510 frame_data,
3511 arraysize(kContinuationFrameData),
3512 kContinuationFrameData,
3513 arraysize(kContinuationFrameData));
3517 TEST_P(SpdyFramerTest, CreateAltSvc) {
3518 if (spdy_version_ <= SPDY3) {
3519 return;
3522 SpdyFramer framer(spdy_version_);
3524 const char kDescription[] = "ALTSVC frame";
3525 const char kType = static_cast<unsigned char>(
3526 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3527 const unsigned char kFrameData[] = {
3528 0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
3529 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h',
3530 'o', 's', 't', ':', '4', '4', '3', '"', ';', ' ', 'm', 'a',
3531 '=', '5', ',', 'p', '%', '2', '2', '%', '3', 'D', 'i', '%',
3532 '3', 'A', 'd', '=', '"', 'h', '_', '\\', '\\', 'o', '\\', '"',
3533 's', 't', ':', '1', '2', '3', '"', ';', ' ', 'm', 'a', '=',
3534 '4', '2', ';', ' ', 'p', '=', '0', '.', '2', '0',
3536 SpdyAltSvcIR altsvc_ir(3);
3537 altsvc_ir.set_origin("origin");
3538 altsvc_ir.add_altsvc(
3539 SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0));
3540 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
3541 "p\"=i:d", "h_\\o\"st", 123, 42, 0.2));
3542 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3543 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3546 TEST_P(SpdyFramerTest, CreatePriority) {
3547 if (spdy_version_ <= SPDY3) {
3548 return;
3551 SpdyFramer framer(spdy_version_);
3553 const char kDescription[] = "PRIORITY frame";
3554 const unsigned char kType = static_cast<unsigned char>(
3555 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3556 const unsigned char kFrameData[] = {
3557 0x00, 0x00, 0x05, kType, 0x00,
3558 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3559 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3560 0x10, // Weight = 16
3562 SpdyPriorityIR priority_ir(2, 1, 16, true);
3563 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3564 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3565 SpdyPriorityIR priority2(2);
3566 priority2.set_parent_stream_id(1);
3567 priority2.set_weight(16);
3568 priority2.set_exclusive(true);
3569 frame.reset(framer.SerializeFrame(priority2));
3570 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3573 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3574 if (spdy_version_ > SPDY3) {
3575 // SYN_STREAM not supported in SPDY>3
3576 return;
3578 SpdyFramer framer(spdy_version_);
3579 SpdySynStreamIR syn_stream(1);
3580 syn_stream.set_priority(1);
3581 syn_stream.SetHeader("aa", "vv");
3582 syn_stream.SetHeader("bb", "ww");
3583 SpdyHeaderBlock headers = syn_stream.header_block();
3584 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3585 EXPECT_TRUE(control_frame.get() != NULL);
3586 TestSpdyVisitor visitor(spdy_version_);
3587 visitor.use_compression_ = true;
3588 visitor.SimulateInFramer(
3589 reinterpret_cast<unsigned char*>(control_frame->data()),
3590 control_frame->size());
3591 EXPECT_EQ(1, visitor.syn_frame_count_);
3592 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3595 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3596 if (spdy_version_ > SPDY3) {
3597 return;
3599 SpdyFramer framer(spdy_version_);
3600 SpdySynReplyIR syn_reply(1);
3601 syn_reply.SetHeader("alpha", "beta");
3602 syn_reply.SetHeader("gamma", "delta");
3603 SpdyHeaderBlock headers = syn_reply.header_block();
3604 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3605 EXPECT_TRUE(control_frame.get() != NULL);
3606 TestSpdyVisitor visitor(spdy_version_);
3607 visitor.use_compression_ = true;
3608 visitor.SimulateInFramer(
3609 reinterpret_cast<unsigned char*>(control_frame->data()),
3610 control_frame->size());
3611 if (IsHttp2()) {
3612 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3613 EXPECT_EQ(1, visitor.headers_frame_count_);
3614 } else {
3615 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3616 EXPECT_EQ(0, visitor.headers_frame_count_);
3618 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3621 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3622 SpdyFramer framer(spdy_version_);
3623 SpdyHeadersIR headers_ir(1);
3624 headers_ir.SetHeader("alpha", "beta");
3625 headers_ir.SetHeader("gamma", "delta");
3626 SpdyHeaderBlock headers = headers_ir.header_block();
3627 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3628 EXPECT_TRUE(control_frame.get() != NULL);
3629 TestSpdyVisitor visitor(spdy_version_);
3630 visitor.use_compression_ = true;
3631 visitor.SimulateInFramer(
3632 reinterpret_cast<unsigned char*>(control_frame->data()),
3633 control_frame->size());
3634 EXPECT_EQ(1, visitor.headers_frame_count_);
3635 // control_frame_header_data_count_ depends on the random sequence
3636 // produced by rand(), so adding, removing or running single tests
3637 // alters this value. The best we can do is assert that it happens
3638 // at least twice.
3639 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3640 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3641 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3642 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3645 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3646 SpdyFramer framer(spdy_version_);
3647 SpdyHeadersIR headers_ir(1);
3648 headers_ir.set_fin(true);
3649 headers_ir.SetHeader("alpha", "beta");
3650 headers_ir.SetHeader("gamma", "delta");
3651 SpdyHeaderBlock headers = headers_ir.header_block();
3652 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3653 EXPECT_TRUE(control_frame.get() != NULL);
3654 TestSpdyVisitor visitor(spdy_version_);
3655 visitor.use_compression_ = true;
3656 visitor.SimulateInFramer(
3657 reinterpret_cast<unsigned char*>(control_frame->data()),
3658 control_frame->size());
3659 EXPECT_EQ(1, visitor.headers_frame_count_);
3660 // control_frame_header_data_count_ depends on the random sequence
3661 // produced by rand(), so adding, removing or running single tests
3662 // alters this value. The best we can do is assert that it happens
3663 // at least twice.
3664 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3665 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3666 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3667 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3670 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3671 if (spdy_version_ > SPDY3) {
3672 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3673 return;
3675 // First find the size of the header value in order to just reach the control
3676 // frame max size.
3677 SpdyFramer framer(spdy_version_);
3678 framer.set_enable_compression(false);
3679 SpdySynStreamIR syn_stream(1);
3680 syn_stream.set_priority(1);
3681 syn_stream.SetHeader("aa", "");
3682 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3683 const size_t kBigValueSize =
3684 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3686 // Create a frame at exactly that size.
3687 string big_value(kBigValueSize, 'x');
3688 syn_stream.SetHeader("aa", big_value);
3689 control_frame.reset(framer.SerializeSynStream(syn_stream));
3690 EXPECT_TRUE(control_frame.get() != NULL);
3691 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3692 control_frame->size());
3694 TestSpdyVisitor visitor(spdy_version_);
3695 visitor.SimulateInFramer(
3696 reinterpret_cast<unsigned char*>(control_frame->data()),
3697 control_frame->size());
3698 EXPECT_TRUE(visitor.header_buffer_valid_);
3699 EXPECT_EQ(0, visitor.error_count_);
3700 EXPECT_EQ(1, visitor.syn_frame_count_);
3701 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3702 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3703 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3706 TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
3707 if (spdy_version_ > SPDY3) {
3708 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3709 return;
3711 if (spdy_version_ < SPDY3) {
3712 // Since SPDY/2 uses 16 bit header field lengths, one cannot easily create a
3713 // header frame of maximum size.
3714 return;
3716 // First find the size of the header value in order to just reach the control
3717 // frame max size.
3718 SpdyFramer framer(spdy_version_);
3719 framer.set_enable_compression(false);
3720 SpdySynStreamIR syn_stream(1);
3721 syn_stream.SetHeader("aa", "");
3722 syn_stream.set_priority(1);
3723 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3724 const size_t kBigValueSize =
3725 SpdyConstants::GetFrameMaximumSize(spdy_version_) - control_frame->size();
3727 // Create a frame at exatly that size.
3728 string big_value(kBigValueSize, 'x');
3729 syn_stream.SetHeader("aa", big_value);
3730 // Upstream branches here and wraps HTTP/2 with EXPECT_DEBUG_DFATAL. We
3731 // neither support that in Chromium, nor do we use the same DFATAL (see
3732 // SpdyFrameBuilder::WriteFramePrefix()).
3733 control_frame.reset(framer.SerializeSynStream(syn_stream));
3735 EXPECT_TRUE(control_frame.get() != NULL);
3736 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_),
3737 control_frame->size());
3739 TestSpdyVisitor visitor(spdy_version_);
3740 visitor.SimulateInFramer(
3741 reinterpret_cast<unsigned char*>(control_frame->data()),
3742 control_frame->size());
3743 EXPECT_TRUE(visitor.header_buffer_valid_);
3744 EXPECT_EQ(0, visitor.error_count_);
3745 EXPECT_EQ(1, visitor.syn_frame_count_);
3748 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3749 if (spdy_version_ <= SPDY3) {
3750 return;
3752 SpdyFramer framer(spdy_version_);
3753 framer.set_enable_compression(false);
3754 SpdyHeadersIR headers(1);
3755 headers.set_padding_len(256);
3757 // Exact payload length will change with HPACK, but this should be long
3758 // enough to cause an overflow.
3759 const size_t kBigValueSize = kControlFrameSizeLimit;
3760 string big_value(kBigValueSize, 'x');
3761 headers.SetHeader("aa", big_value);
3762 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3763 EXPECT_TRUE(control_frame.get() != NULL);
3764 EXPECT_GT(control_frame->size(),
3765 TestSpdyVisitor::sent_control_frame_max_size());
3767 TestSpdyVisitor visitor(spdy_version_);
3768 visitor.SimulateInFramer(
3769 reinterpret_cast<unsigned char*>(control_frame->data()),
3770 control_frame->size());
3771 EXPECT_TRUE(visitor.header_buffer_valid_);
3772 EXPECT_EQ(0, visitor.error_count_);
3773 EXPECT_EQ(1, visitor.headers_frame_count_);
3774 EXPECT_EQ(16, visitor.continuation_count_);
3775 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3778 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3779 if (spdy_version_ <= SPDY3) {
3780 return;
3782 SpdyFramer framer(spdy_version_);
3783 framer.set_enable_compression(false);
3784 SpdyPushPromiseIR push_promise(1, 2);
3785 push_promise.set_padding_len(256);
3787 // Exact payload length will change with HPACK, but this should be long
3788 // enough to cause an overflow.
3789 const size_t kBigValueSize = kControlFrameSizeLimit;
3790 string big_value(kBigValueSize, 'x');
3791 push_promise.SetHeader("aa", big_value);
3792 scoped_ptr<SpdyFrame> control_frame(
3793 framer.SerializePushPromise(push_promise));
3794 EXPECT_TRUE(control_frame.get() != NULL);
3795 EXPECT_GT(control_frame->size(),
3796 TestSpdyVisitor::sent_control_frame_max_size());
3798 TestSpdyVisitor visitor(spdy_version_);
3799 visitor.SimulateInFramer(
3800 reinterpret_cast<unsigned char*>(control_frame->data()),
3801 control_frame->size());
3802 EXPECT_TRUE(visitor.header_buffer_valid_);
3803 EXPECT_EQ(0, visitor.error_count_);
3804 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3805 EXPECT_EQ(16, visitor.continuation_count_);
3806 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3809 // Check that the framer stops delivering header data chunks once the visitor
3810 // declares it doesn't want any more. This is important to guard against
3811 // "zip bomb" types of attacks.
3812 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3813 const size_t kHeaderBufferChunks = 4;
3814 const size_t kHeaderBufferSize =
3815 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3816 const size_t kBigValueSize = kHeaderBufferSize * 2;
3817 string big_value(kBigValueSize, 'x');
3818 SpdyFramer framer(spdy_version_);
3819 SpdyHeadersIR headers(1);
3820 headers.set_priority(1);
3821 headers.set_fin(true);
3822 headers.SetHeader("aa", big_value);
3823 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3824 EXPECT_TRUE(control_frame.get() != NULL);
3825 TestSpdyVisitor visitor(spdy_version_);
3826 visitor.set_header_buffer_size(kHeaderBufferSize);
3827 visitor.use_compression_ = true;
3828 visitor.SimulateInFramer(
3829 reinterpret_cast<unsigned char*>(control_frame->data()),
3830 control_frame->size());
3831 EXPECT_FALSE(visitor.header_buffer_valid_);
3832 EXPECT_EQ(1, visitor.error_count_);
3833 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3834 visitor.framer_.error_code())
3835 << SpdyFramer::ErrorCodeToString(framer.error_code());
3837 // The framer should have stoped delivering chunks after the visitor
3838 // signaled "stop" by returning false from OnControlFrameHeaderData().
3840 // control_frame_header_data_count_ depends on the random sequence
3841 // produced by rand(), so adding, removing or running single tests
3842 // alters this value. The best we can do is assert that it happens
3843 // at least kHeaderBufferChunks + 1.
3844 EXPECT_LE(kHeaderBufferChunks + 1,
3845 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3846 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3848 // The framer should not have sent half-close to the visitor.
3849 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3852 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3853 if (spdy_version_ > SPDY3) {
3854 // Deflate compression doesn't apply to HPACK.
3855 return;
3857 SpdyFramer framer(spdy_version_);
3858 framer.set_enable_compression(false);
3859 // Construct a SYN_STREAM control frame without compressing the header block,
3860 // and have the framer try to decompress it. This will cause the framer to
3861 // deal with a decompression error.
3862 SpdySynStreamIR syn_stream(1);
3863 syn_stream.set_priority(1);
3864 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3865 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3866 TestSpdyVisitor visitor(spdy_version_);
3867 visitor.use_compression_ = true;
3868 visitor.SimulateInFramer(
3869 reinterpret_cast<unsigned char*>(control_frame->data()),
3870 control_frame->size());
3871 EXPECT_EQ(1, visitor.error_count_);
3872 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3873 << SpdyFramer::ErrorCodeToString(framer.error_code());
3874 EXPECT_EQ(0u, visitor.header_buffer_length_);
3877 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3878 SpdyFramer framer(spdy_version_);
3879 // Create a GoAway frame that has a few extra bytes at the end.
3880 // We create enough overhead to overflow the framer's control frame buffer.
3881 ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
3882 const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
3883 const unsigned char kV3FrameData[] = { // Also applies for V2.
3884 0x80, spdy_version_ch_, 0x00, 0x07,
3885 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
3886 0x00, 0x00, 0x00, 0x00, // Stream ID
3887 0x00, 0x00, 0x00, 0x00, // Status
3890 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3891 // since it may carry opaque data. Verify that minimal length is tested.
3892 ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
3893 const size_t less_than_min_length =
3894 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3895 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3896 const unsigned char kH2FrameData[] = {
3897 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
3898 0x00, 0x00, 0x00, 0x00,
3899 0x00, 0x00, 0x00, 0x00, // Stream Id
3900 0x00, 0x00, 0x00, 0x00, // Status
3901 0x00,
3903 const size_t pad_length =
3904 length + framer.GetControlFrameHeaderSize() -
3905 (IsHttp2() ? sizeof(kH2FrameData) : sizeof(kV3FrameData));
3906 string pad(pad_length, 'A');
3907 TestSpdyVisitor visitor(spdy_version_);
3909 if (IsHttp2()) {
3910 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3911 } else {
3912 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3914 visitor.SimulateInFramer(
3915 reinterpret_cast<const unsigned char*>(pad.c_str()),
3916 pad.length());
3918 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3919 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3920 visitor.framer_.error_code())
3921 << SpdyFramer::ErrorCodeToString(framer.error_code());
3922 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3925 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3926 SpdyFramer framer(spdy_version_);
3927 SpdySettingsIR settings_ir;
3928 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3929 SetFrameLength(control_frame.get(), 0, spdy_version_);
3930 TestSpdyVisitor visitor(spdy_version_);
3931 visitor.use_compression_ = false;
3932 visitor.SimulateInFramer(
3933 reinterpret_cast<unsigned char*>(control_frame->data()),
3934 framer.GetControlFrameHeaderSize());
3935 if (spdy_version_ <= SPDY3) {
3936 // Should generate an error, since zero-len settings frames are unsupported.
3937 EXPECT_EQ(1, visitor.error_count_);
3938 } else {
3939 // Zero-len settings frames are permitted as of HTTP/2.
3940 EXPECT_EQ(0, visitor.error_count_);
3944 // Tests handling of SETTINGS frames with invalid length.
3945 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3946 SpdyFramer framer(spdy_version_);
3947 SpdySettingsIR settings_ir;
3949 // Add a setting to pad the frame so that we don't get a buffer overflow when
3950 // calling SimulateInFramer() below.
3951 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3952 false,
3953 false,
3954 0x00000002);
3955 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3956 const size_t kNewLength = 14;
3957 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3958 TestSpdyVisitor visitor(spdy_version_);
3959 visitor.use_compression_ = false;
3960 visitor.SimulateInFramer(
3961 reinterpret_cast<unsigned char*>(control_frame->data()),
3962 framer.GetControlFrameHeaderSize() + kNewLength);
3963 // Should generate an error, since its not possible to have a
3964 // settings frame of length kNewLength.
3965 EXPECT_EQ(1, visitor.error_count_);
3968 // Tests handling of SETTINGS frames larger than the frame buffer size.
3969 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3970 SpdyFramer framer(spdy_version_);
3971 SpdySettingsIR settings_ir;
3972 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3973 false, // persist
3974 false, // persisted
3976 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3977 false, // persist
3978 false, // persisted
3980 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3981 false, // persist
3982 false, // persisted
3985 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3986 EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame->size());
3987 TestSpdyVisitor visitor(spdy_version_);
3988 visitor.use_compression_ = false;
3990 // Read all at once.
3991 visitor.SimulateInFramer(
3992 reinterpret_cast<unsigned char*>(control_frame->data()),
3993 control_frame->size());
3994 EXPECT_EQ(0, visitor.error_count_);
3995 EXPECT_EQ(3, visitor.setting_count_);
3996 if (spdy_version_ > SPDY3) {
3997 EXPECT_EQ(1, visitor.settings_ack_sent_);
4000 // Read data in small chunks.
4001 size_t framed_data = 0;
4002 size_t unframed_data = control_frame->size();
4003 size_t kReadChunkSize = 5; // Read five bytes at a time.
4004 while (unframed_data > 0) {
4005 size_t to_read = std::min(kReadChunkSize, unframed_data);
4006 visitor.SimulateInFramer(
4007 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
4008 to_read);
4009 unframed_data -= to_read;
4010 framed_data += to_read;
4012 EXPECT_EQ(0, visitor.error_count_);
4013 EXPECT_EQ(3 * 2, visitor.setting_count_);
4014 if (spdy_version_ > SPDY3) {
4015 EXPECT_EQ(2, visitor.settings_ack_sent_);
4019 // Tests handling of SETTINGS frame with duplicate entries.
4020 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
4021 SpdyFramer framer(spdy_version_);
4023 const unsigned char kV2FrameData[] = {
4024 0x80, spdy_version_ch_, 0x00, 0x04,
4025 0x00, 0x00, 0x00, 0x1C,
4026 0x00, 0x00, 0x00, 0x03,
4027 0x01, 0x00, 0x00, 0x00, // 1st Setting
4028 0x00, 0x00, 0x00, 0x02,
4029 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
4030 0x00, 0x00, 0x00, 0x03,
4031 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4032 0x00, 0x00, 0x00, 0x03,
4034 const unsigned char kV3FrameData[] = {
4035 0x80, spdy_version_ch_, 0x00, 0x04,
4036 0x00, 0x00, 0x00, 0x1C,
4037 0x00, 0x00, 0x00, 0x03,
4038 0x00, 0x00, 0x00, 0x01, // 1st Setting
4039 0x00, 0x00, 0x00, 0x02,
4040 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
4041 0x00, 0x00, 0x00, 0x03,
4042 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
4043 0x00, 0x00, 0x00, 0x03,
4045 const unsigned char kH2FrameData[] = {
4046 0x00, 0x00, 0x12, 0x04,
4047 0x00, 0x00, 0x00, 0x00,
4048 0x00, 0x00, 0x01, // 1st Setting
4049 0x00, 0x00, 0x00, 0x02,
4050 0x00, 0x01, // 2nd (duplicate) Setting
4051 0x00, 0x00, 0x00, 0x03,
4052 0x00, 0x03, // 3rd (unprocessed) Setting
4053 0x00, 0x00, 0x00, 0x03,
4056 TestSpdyVisitor visitor(spdy_version_);
4057 visitor.use_compression_ = false;
4058 if (IsSpdy2()) {
4059 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4060 } else if (IsSpdy3()) {
4061 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4062 } else {
4063 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4066 if (!IsHttp2()) {
4067 EXPECT_EQ(1, visitor.setting_count_);
4068 EXPECT_EQ(1, visitor.error_count_);
4069 } else {
4070 // In HTTP/2, duplicate settings are allowed;
4071 // each setting replaces the previous value for that setting.
4072 EXPECT_EQ(3, visitor.setting_count_);
4073 EXPECT_EQ(0, visitor.error_count_);
4074 EXPECT_EQ(1, visitor.settings_ack_sent_);
4078 // Tests handling of SETTINGS frame with a setting we don't recognize.
4079 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
4080 SpdyFramer framer(spdy_version_);
4082 const unsigned char kV2FrameData[] = {
4083 0x80, spdy_version_ch_, 0x00, 0x04,
4084 0x00, 0x00, 0x00, 0x1C,
4085 0x00, 0x00, 0x00, 0x01,
4086 0x10, 0x00, 0x00, 0x00, // 1st Setting
4087 0x00, 0x00, 0x00, 0x02,
4089 const unsigned char kV3FrameData[] = {
4090 0x80, spdy_version_ch_, 0x00, 0x04,
4091 0x00, 0x00, 0x00, 0x1C,
4092 0x00, 0x00, 0x00, 0x01,
4093 0x00, 0x00, 0x00, 0x10, // 1st Setting
4094 0x00, 0x00, 0x00, 0x02,
4096 const unsigned char kH2FrameData[] = {
4097 0x00, 0x00, 0x06, 0x04,
4098 0x00, 0x00, 0x00, 0x00,
4099 0x00, 0x00, 0x10, // 1st Setting
4100 0x00, 0x00, 0x00, 0x02,
4103 TestSpdyVisitor visitor(spdy_version_);
4104 visitor.use_compression_ = false;
4105 if (IsSpdy2()) {
4106 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4107 } else if (IsSpdy3()) {
4108 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4109 } else {
4110 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4113 if (!IsHttp2()) {
4114 EXPECT_EQ(0, visitor.setting_count_);
4115 EXPECT_EQ(1, visitor.error_count_);
4116 } else {
4117 // In HTTP/2, we ignore unknown settings because of extensions.
4118 EXPECT_EQ(0, visitor.setting_count_);
4119 EXPECT_EQ(0, visitor.error_count_);
4123 // Tests handling of SETTINGS frame with entries out of order.
4124 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
4125 SpdyFramer framer(spdy_version_);
4127 const unsigned char kV2FrameData[] = {
4128 0x80, spdy_version_ch_, 0x00, 0x04,
4129 0x00, 0x00, 0x00, 0x1C,
4130 0x00, 0x00, 0x00, 0x03,
4131 0x02, 0x00, 0x00, 0x00, // 1st Setting
4132 0x00, 0x00, 0x00, 0x02,
4133 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4134 0x00, 0x00, 0x00, 0x03,
4135 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4136 0x00, 0x00, 0x00, 0x03,
4138 const unsigned char kV3FrameData[] = {
4139 0x80, spdy_version_ch_, 0x00, 0x04,
4140 0x00, 0x00, 0x00, 0x1C,
4141 0x00, 0x00, 0x00, 0x03,
4142 0x00, 0x00, 0x00, 0x02, // 1st Setting
4143 0x00, 0x00, 0x00, 0x02,
4144 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4145 0x00, 0x00, 0x00, 0x03,
4146 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4147 0x00, 0x00, 0x00, 0x03,
4149 const unsigned char kH2FrameData[] = {
4150 0x00, 0x00, 0x12, 0x04,
4151 0x00, 0x00, 0x00, 0x00,
4152 0x00, 0x00, 0x02, // 1st Setting
4153 0x00, 0x00, 0x00, 0x02,
4154 0x00, 0x01, // 2nd (out of order) Setting
4155 0x00, 0x00, 0x00, 0x03,
4156 0x00, 0x03, // 3rd (unprocessed) Setting
4157 0x00, 0x00, 0x00, 0x03,
4160 TestSpdyVisitor visitor(spdy_version_);
4161 visitor.use_compression_ = false;
4162 if (IsSpdy2()) {
4163 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4164 } else if (IsSpdy3()) {
4165 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4166 } else {
4167 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4170 if (!IsHttp2()) {
4171 EXPECT_EQ(1, visitor.setting_count_);
4172 EXPECT_EQ(1, visitor.error_count_);
4173 } else {
4174 // In HTTP/2, settings are allowed in any order.
4175 EXPECT_EQ(3, visitor.setting_count_);
4176 EXPECT_EQ(0, visitor.error_count_);
4180 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4181 if (spdy_version_ <= SPDY3) {
4182 return;
4184 SpdyFramer framer(spdy_version_);
4186 const unsigned char kFrameData[] = {
4187 0x00, 0x00, 0x00, 0x04, 0x01,
4188 0x00, 0x00, 0x00, 0x00,
4191 TestSpdyVisitor visitor(spdy_version_);
4192 visitor.use_compression_ = false;
4193 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4195 EXPECT_EQ(0, visitor.error_count_);
4196 EXPECT_EQ(0, visitor.setting_count_);
4197 EXPECT_EQ(1, visitor.settings_ack_received_);
4200 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4201 if (spdy_version_ <= SPDY3) {
4202 return;
4205 const int kPaddingLen = 119;
4206 const char data_payload[] = "hello";
4208 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4209 SpdyFramer framer(spdy_version_);
4210 framer.set_visitor(&visitor);
4212 SpdyDataIR data_ir(1, data_payload);
4213 data_ir.set_padding_len(kPaddingLen);
4214 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4215 ASSERT_TRUE(frame.get() != NULL);
4217 int bytes_consumed = 0;
4219 // Send the frame header.
4220 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4221 kPaddingLen + strlen(data_payload),
4222 false));
4223 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4224 framer.ProcessInput(frame->data(),
4225 framer.GetDataFrameMinimumSize()));
4226 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4227 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4228 bytes_consumed += framer.GetDataFrameMinimumSize();
4230 // Send the padding length field.
4231 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
4232 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4233 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4234 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4235 bytes_consumed += 1;
4237 // Send the first two bytes of the data payload, i.e., "he".
4238 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4239 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4240 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4241 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4242 bytes_consumed += 2;
4244 // Send the rest three bytes of the data payload, i.e., "llo".
4245 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4246 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4247 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4248 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4249 bytes_consumed += 3;
4251 // Send the first 100 bytes of the padding payload.
4252 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
4253 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4254 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4255 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4256 bytes_consumed += 100;
4258 // Send rest of the padding payload.
4259 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
4260 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4261 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READY_FOR_FRAME);
4262 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4265 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4266 SpdyFramer framer(spdy_version_);
4267 scoped_ptr<SpdyFrame> control_frame(
4268 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4269 TestSpdyVisitor visitor(spdy_version_);
4270 visitor.SimulateInFramer(
4271 reinterpret_cast<unsigned char*>(control_frame->data()),
4272 control_frame->size());
4273 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4274 EXPECT_EQ(2, visitor.last_window_update_delta_);
4277 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4278 if (!IsSpdy3()) {
4279 return;
4281 SpdyFramer framer(spdy_version_);
4282 const unsigned char kV3FrameData[] = { // Also applies for V2.
4283 0x80, spdy_version_ch_, 0x00, 0x0A,
4284 0x00, 0x00, 0x00, 0x33,
4285 0x00, 0x03, 0x00, 0x00,
4286 0x00, 0x05, 'p', 'r',
4287 'o', 'o', 'f', 0x00,
4288 0x00, 0x00, 0x06, 'a',
4289 ' ', 'c', 'e', 'r',
4290 't', 0x00, 0x00, 0x00,
4291 0x0C, 'a', 'n', 'o',
4292 't', 'h', 'e', 'r',
4293 ' ', 'c', 'e', 'r',
4294 't', 0x00, 0x00, 0x00,
4295 0x0A, 'f', 'i', 'n',
4296 'a', 'l', ' ', 'c',
4297 'e', 'r', 't',
4299 TestSpdyVisitor visitor(spdy_version_);
4300 visitor.use_compression_ = false;
4301 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4302 EXPECT_EQ(0, visitor.error_count_);
4305 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4306 if (!IsSpdy3()) {
4307 return;
4309 SpdyFramer framer(spdy_version_);
4310 const unsigned char kV3FrameData[] = { // Also applies for V2.
4311 0x80, spdy_version_ch_, 0x00, 0x0A,
4312 0x00, 0x00, 0x00, 0x33,
4313 0x00, 0x03, 0x00, 0x00,
4314 0x00, 0x05, 'p', 'r',
4315 'o', 'o', 'f', 0x00,
4316 0x00, 0x00, 0x06, 'a',
4317 ' ', 'c', 'e', 'r',
4318 't', 0x00, 0x00, 0x00,
4319 0x0C, 'a', 'n', 'o',
4320 't', 'h', 'e', 'r',
4321 ' ', 'c', 'e', 'r',
4322 't', 0x00, 0x00, 0x00,
4323 0x0A, 'f', 'i', 'n',
4324 'a', 'l', ' ', 'c',
4325 'e', 'r', 't',
4327 TestSpdyVisitor visitor(spdy_version_);
4328 visitor.use_compression_ = false;
4329 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4330 arraysize(kV3FrameData));
4331 scoped_ptr<SpdyFrame> control_frame(
4332 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4333 multiple_frame_data.append(string(control_frame->data(),
4334 control_frame->size()));
4335 visitor.SimulateInFramer(
4336 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4337 multiple_frame_data.length());
4338 EXPECT_EQ(0, visitor.error_count_);
4339 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4340 EXPECT_EQ(2, visitor.last_window_update_delta_);
4343 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4344 if (spdy_version_ <= SPDY3) {
4345 return;
4348 SpdyFramer framer(spdy_version_);
4349 SpdyPushPromiseIR push_promise(42, 57);
4350 push_promise.SetHeader("foo", "bar");
4351 push_promise.SetHeader("bar", "foofoo");
4352 SpdyHeaderBlock headers = push_promise.header_block();
4353 scoped_ptr<SpdySerializedFrame> frame(
4354 framer.SerializePushPromise(push_promise));
4355 EXPECT_TRUE(frame.get() != NULL);
4356 TestSpdyVisitor visitor(spdy_version_);
4357 visitor.use_compression_ = true;
4358 visitor.SimulateInFramer(
4359 reinterpret_cast<unsigned char*>(frame->data()),
4360 frame->size());
4361 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4362 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4363 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4366 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4367 if (spdy_version_ <= SPDY3) {
4368 return;
4371 const unsigned char kInput[] = {
4372 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4373 0x00, 0x00, 0x00, 0x01, // Stream 1
4374 0x03, // Padding of 3.
4375 0x00, 0x06, 0x63, 0x6f,
4376 0x6f, 0x6b, 0x69, 0x65,
4377 0x07, 0x66, 0x6f, 0x6f,
4378 0x3d, 0x62, 0x61, 0x72,
4379 0x00, 0x00, 0x00,
4381 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4382 0x00, 0x00, 0x00, 0x01, // Stream 1
4383 0x00, 0x06, 0x63, 0x6f,
4384 0x6f, 0x6b, 0x69, 0x65,
4385 0x08, 0x62, 0x61, 0x7a,
4386 0x3d, 0x62, 0x69, 0x6e,
4387 0x67, 0x00, 0x06, 0x63,
4389 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4390 0x00, 0x00, 0x00, 0x01, // Stream 1
4391 0x6f, 0x6f, 0x6b, 0x69,
4392 0x65, 0x00, 0x00, 0x04,
4393 0x6e, 0x61, 0x6d, 0x65,
4394 0x05, 0x76, 0x61, 0x6c,
4395 0x75, 0x65,
4398 TestSpdyVisitor visitor(spdy_version_);
4399 visitor.SimulateInFramer(kInput, sizeof(kInput));
4401 EXPECT_EQ(0, visitor.error_count_);
4402 EXPECT_EQ(1, visitor.headers_frame_count_);
4403 EXPECT_EQ(2, visitor.continuation_count_);
4404 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4405 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4407 EXPECT_THAT(visitor.headers_,
4408 testing::ElementsAre(
4409 testing::Pair("cookie", "foo=bar; baz=bing; "),
4410 testing::Pair("name", "value")));
4413 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4414 if (spdy_version_ <= SPDY3) {
4415 return;
4418 const unsigned char kInput[] = {
4419 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4420 0x00, 0x00, 0x00, 0x01, // Stream 1
4421 0x00, 0x06, 0x63, 0x6f,
4422 0x6f, 0x6b, 0x69, 0x65,
4423 0x07, 0x66, 0x6f, 0x6f,
4424 0x3d, 0x62, 0x61, 0x72,
4426 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4427 0x00, 0x00, 0x00, 0x01, // Stream 1
4428 0x00, 0x06, 0x63, 0x6f,
4429 0x6f, 0x6b, 0x69, 0x65,
4430 0x08, 0x62, 0x61, 0x7a,
4431 0x3d, 0x62, 0x69, 0x6e,
4432 0x67, 0x00, 0x06, 0x63,
4434 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4435 0x00, 0x00, 0x00, 0x01, // Stream 1
4436 0x6f, 0x6f, 0x6b, 0x69,
4437 0x65, 0x00, 0x00, 0x04,
4438 0x6e, 0x61, 0x6d, 0x65,
4439 0x05, 0x76, 0x61, 0x6c,
4440 0x75, 0x65,
4443 SpdyFramer framer(spdy_version_);
4444 TestSpdyVisitor visitor(spdy_version_);
4445 visitor.SimulateInFramer(kInput, sizeof(kInput));
4447 EXPECT_EQ(0, visitor.error_count_);
4448 EXPECT_EQ(1, visitor.headers_frame_count_);
4449 EXPECT_EQ(2, visitor.continuation_count_);
4450 EXPECT_EQ(1, visitor.fin_flag_count_);
4451 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4452 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4454 EXPECT_THAT(visitor.headers_,
4455 testing::ElementsAre(
4456 testing::Pair("cookie", "foo=bar; baz=bing; "),
4457 testing::Pair("name", "value")));
4460 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4461 if (spdy_version_ <= SPDY3) {
4462 return;
4465 const unsigned char kInput[] = {
4466 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4467 0x08, 0x00, 0x00, 0x00, // PADDED
4468 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4469 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4470 0x63, 0x6f, 0x6f, 0x6b,
4471 0x69, 0x65, 0x07, 0x66,
4472 0x6f, 0x6f, 0x3d, 0x62,
4473 0x61, 0x72, 0x00, 0x00,
4475 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4476 0x00, 0x00, 0x00, 0x00,
4477 0x01, 0x00, 0x06, 0x63, // Stream 1
4478 0x6f, 0x6f, 0x6b, 0x69,
4479 0x65, 0x08, 0x62, 0x61,
4480 0x7a, 0x3d, 0x62, 0x69,
4481 0x6e, 0x67, 0x00, 0x06,
4482 0x63,
4484 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4485 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4486 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4487 0x69, 0x65, 0x00, 0x00,
4488 0x04, 0x6e, 0x61, 0x6d,
4489 0x65, 0x05, 0x76, 0x61,
4490 0x6c, 0x75, 0x65,
4493 SpdyFramer framer(spdy_version_);
4494 TestSpdyVisitor visitor(spdy_version_);
4495 visitor.SimulateInFramer(kInput, sizeof(kInput));
4497 EXPECT_EQ(0, visitor.error_count_);
4498 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4499 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4500 EXPECT_EQ(2, visitor.continuation_count_);
4501 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4502 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4504 EXPECT_THAT(visitor.headers_,
4505 testing::ElementsAre(
4506 testing::Pair("cookie", "foo=bar; baz=bing; "),
4507 testing::Pair("name", "value")));
4510 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4511 if (spdy_version_ <= SPDY3) {
4512 return;
4515 const unsigned char kInput[] = {
4516 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4517 0x00, 0x00, 0x00, 0x01, // Stream 1
4518 0x00, 0x06, 0x63, 0x6f,
4519 0x6f, 0x6b, 0x69, 0x65,
4520 0x07, 0x66, 0x6f, 0x6f,
4521 0x3d, 0x62, 0x61, 0x72,
4523 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4524 0x00, 0x00, 0x00, 0x02, // Stream 2
4525 0x00, 0x06, 0x63, 0x6f,
4526 0x6f, 0x6b, 0x69, 0x65,
4527 0x08, 0x62, 0x61, 0x7a,
4528 0x3d, 0x62, 0x69, 0x6e,
4529 0x67, 0x00, 0x06, 0x63,
4532 SpdyFramer framer(spdy_version_);
4533 TestSpdyVisitor visitor(spdy_version_);
4534 framer.set_visitor(&visitor);
4535 visitor.SimulateInFramer(kInput, sizeof(kInput));
4537 EXPECT_EQ(1, visitor.error_count_);
4538 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4539 visitor.framer_.error_code())
4540 << SpdyFramer::ErrorCodeToString(framer.error_code());
4541 EXPECT_EQ(1, visitor.headers_frame_count_);
4542 EXPECT_EQ(0, visitor.continuation_count_);
4543 EXPECT_EQ(0u, visitor.header_buffer_length_);
4546 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4547 if (spdy_version_ <= SPDY3) {
4548 return;
4551 const unsigned char kInput[] = {
4552 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4553 0x00, 0x00, 0x00, 0x01, // Stream 1
4554 0x00, 0x06, 0x63, 0x6f,
4555 0x6f, 0x6b, 0x69, 0x65,
4556 0x07, 0x66, 0x6f, 0x6f,
4557 0x3d, 0x62, 0x61, 0x72,
4560 SpdyFramer framer(spdy_version_);
4561 TestSpdyVisitor visitor(spdy_version_);
4562 framer.set_visitor(&visitor);
4563 visitor.SimulateInFramer(kInput, sizeof(kInput));
4565 EXPECT_EQ(1, visitor.error_count_);
4566 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4567 visitor.framer_.error_code())
4568 << SpdyFramer::ErrorCodeToString(framer.error_code());
4569 EXPECT_EQ(0, visitor.continuation_count_);
4570 EXPECT_EQ(0u, visitor.header_buffer_length_);
4573 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4574 if (spdy_version_ <= SPDY3) {
4575 return;
4578 const unsigned char kInput[] = {
4579 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4580 0x00, 0x00, 0x00, 0x01, // Stream 1
4581 0x00, 0x06, 0x63, 0x6f,
4582 0x6f, 0x6b, 0x69, 0x65,
4583 0x07, 0x66, 0x6f, 0x6f,
4584 0x3d, 0x62, 0x61, 0x72,
4586 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4587 0x00, 0x00, 0x00, 0x04,
4588 0xde, 0xad, 0xbe, 0xef,
4591 SpdyFramer framer(spdy_version_);
4592 TestSpdyVisitor visitor(spdy_version_);
4593 framer.set_visitor(&visitor);
4594 visitor.SimulateInFramer(kInput, sizeof(kInput));
4596 EXPECT_EQ(1, visitor.error_count_);
4597 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4598 visitor.framer_.error_code())
4599 << SpdyFramer::ErrorCodeToString(framer.error_code());
4600 EXPECT_EQ(1, visitor.headers_frame_count_);
4601 EXPECT_EQ(0, visitor.continuation_count_);
4602 EXPECT_EQ(0u, visitor.header_buffer_length_);
4603 EXPECT_EQ(0, visitor.data_frame_count_);
4606 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4607 if (spdy_version_ <= SPDY3) {
4608 return;
4611 const unsigned char kInput[] = {
4612 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4613 0x00, 0x00, 0x00, 0x01, // Stream 1
4614 0x00, 0x06, 0x63, 0x6f,
4615 0x6f, 0x6b, 0x69, 0x65,
4616 0x07, 0x66, 0x6f, 0x6f,
4617 0x3d, 0x62, 0x61, 0x72,
4619 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4620 0x00, 0x00, 0x00, 0x01, // Stream 1
4621 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4622 0x6f, 0x6b, 0x69, 0x65,
4623 0x08, 0x62, 0x61, 0x7a,
4624 0x3d, 0x62, 0x69, 0x6e,
4625 0x67, 0x00, 0x06, 0x63,
4628 SpdyFramer framer(spdy_version_);
4629 TestSpdyVisitor visitor(spdy_version_);
4630 framer.set_visitor(&visitor);
4631 visitor.SimulateInFramer(kInput, sizeof(kInput));
4633 EXPECT_EQ(1, visitor.error_count_);
4634 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4635 visitor.framer_.error_code())
4636 << SpdyFramer::ErrorCodeToString(framer.error_code());
4637 EXPECT_EQ(1, visitor.headers_frame_count_);
4638 EXPECT_EQ(0, visitor.continuation_count_);
4639 EXPECT_EQ(0u, visitor.header_buffer_length_);
4640 EXPECT_EQ(0, visitor.data_frame_count_);
4643 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4644 if (spdy_version_ <= SPDY3) {
4645 return;
4647 const unsigned char kInput[] = {
4648 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4649 0x00, 0x00, 0x00, 0x01, // Stream 1
4650 0xde, 0xad, 0xbe, 0xef,
4651 0xde, 0xad, 0xbe, 0xef,
4652 0xde, 0xad, 0xbe, 0xef,
4655 TestSpdyVisitor visitor(spdy_version_);
4656 visitor.SimulateInFramer(kInput, sizeof(kInput));
4658 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4659 EXPECT_EQ(0, visitor.error_count_);
4660 EXPECT_EQ(12, visitor.data_bytes_);
4661 EXPECT_EQ(0, visitor.fin_frame_count_);
4662 EXPECT_EQ(0, visitor.fin_flag_count_);
4665 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4666 if (spdy_version_ <= SPDY3) {
4667 return;
4669 const unsigned char kInput[] = {
4670 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4671 0x00, 0x00, 0x00, 0x01, // Stream 1
4672 0x00, 0x06, 0x63, 0x6f,
4673 0x6f, 0x6b, 0x69, 0x65,
4674 0x07, 0x66, 0x6f, 0x6f,
4675 0x3d, 0x62, 0x61, 0x72,
4678 TestSpdyVisitor visitor(spdy_version_);
4679 visitor.SimulateInFramer(kInput, sizeof(kInput));
4681 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4682 EXPECT_EQ(0, visitor.error_count_);
4683 EXPECT_EQ(1, visitor.headers_frame_count_);
4684 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4686 EXPECT_THAT(visitor.headers_,
4687 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4690 TEST_P(SpdyFramerTest, ReadGarbage) {
4691 SpdyFramer framer(spdy_version_);
4692 unsigned char garbage_frame[256];
4693 memset(garbage_frame, ~0, sizeof(garbage_frame));
4694 TestSpdyVisitor visitor(spdy_version_);
4695 visitor.use_compression_ = false;
4696 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4697 EXPECT_EQ(1, visitor.error_count_);
4700 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4701 if (spdy_version_ <= SPDY3) {
4702 return;
4704 SpdyFramer framer(spdy_version_);
4706 // The unrecognized frame type should still have a valid length.
4707 const unsigned char unknown_frame[] = {
4708 0x00, 0x00, 0x08, 0xff, 0xff,
4709 0xff, 0xff, 0xff, 0xff,
4710 0xff, 0xff, 0xff, 0xff,
4711 0xff, 0xff, 0xff, 0xff,
4713 TestSpdyVisitor visitor(spdy_version_);
4715 // Simulate the case where the stream id validation checks out.
4716 visitor.on_unknown_frame_result_ = true;
4717 visitor.use_compression_ = false;
4718 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4719 EXPECT_EQ(0, visitor.error_count_);
4721 // Follow it up with a valid control frame to make sure we handle
4722 // subsequent frames correctly.
4723 SpdySettingsIR settings_ir;
4724 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4725 false, // persist
4726 false, // persisted
4727 10);
4728 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4729 visitor.SimulateInFramer(
4730 reinterpret_cast<unsigned char*>(control_frame->data()),
4731 control_frame->size());
4732 EXPECT_EQ(0, visitor.error_count_);
4733 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4734 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4737 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4738 if (!IsHttp2()) {
4739 return;
4741 SpdyFramer framer(spdy_version_);
4742 const unsigned char kFrameData[] = {
4743 0x00, 0x00, 0x08, 0xff, 0xff,
4744 0xff, 0xff, 0xff, 0xff,
4745 0xff, 0xff, 0xff, 0xff,
4746 0xff, 0xff, 0xff, 0xff,
4748 TestSpdyVisitor visitor(spdy_version_);
4749 visitor.use_compression_ = false;
4750 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4751 EXPECT_EQ(1, visitor.error_count_);
4754 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4755 if (IsHttp2()) {
4756 // Not valid for HTTP/2 since there is no version field.
4757 return;
4759 SpdyFramer framer(spdy_version_);
4760 const unsigned char kFrameData[] = {
4761 0x80, spdy_version_ch_, 0xff, 0xff,
4762 0xff, 0xff, 0xff, 0xff,
4764 TestSpdyVisitor visitor(spdy_version_);
4765 visitor.use_compression_ = false;
4766 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4767 EXPECT_EQ(1, visitor.error_count_);
4770 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4771 if (spdy_version_ <= SPDY3) {
4772 return;
4774 const unsigned char kInput[] = {
4775 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4776 0x00, 0x00, 0x00, 0x01, // Stream 1
4777 0xef, 0xef, 0xff, 0xff,
4778 0xff, 0xff, 0xff, 0xff,
4779 0xff, 0xff, 0xff, 0xff,
4780 0xff, 0xff, 0xff, 0xff,
4781 0xff, 0xff,
4784 TestSpdyVisitor visitor(spdy_version_);
4785 visitor.SimulateInFramer(kInput, arraysize(kInput));
4786 EXPECT_EQ(1, visitor.error_count_);
4789 TEST_P(SpdyFramerTest, SizesTest) {
4790 SpdyFramer framer(spdy_version_);
4791 if (IsHttp2()) {
4792 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4793 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4794 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4795 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4796 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4797 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4798 EXPECT_EQ(17u, framer.GetPingSize());
4799 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4800 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4801 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4802 EXPECT_EQ(9u, framer.GetBlockedSize());
4803 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4804 EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
4805 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4806 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4807 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4808 } else {
4809 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4810 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4811 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4812 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4813 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4814 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4815 EXPECT_EQ(12u, framer.GetPingSize());
4816 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4817 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4818 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4819 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4820 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4821 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4825 TEST_P(SpdyFramerTest, StateToStringTest) {
4826 EXPECT_STREQ("ERROR",
4827 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4828 EXPECT_STREQ("FRAME_COMPLETE",
4829 SpdyFramer::StateToString(SpdyFramer::SPDY_FRAME_COMPLETE));
4830 EXPECT_STREQ("READY_FOR_FRAME",
4831 SpdyFramer::StateToString(SpdyFramer::SPDY_READY_FOR_FRAME));
4832 EXPECT_STREQ("READING_COMMON_HEADER",
4833 SpdyFramer::StateToString(
4834 SpdyFramer::SPDY_READING_COMMON_HEADER));
4835 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4836 SpdyFramer::StateToString(
4837 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4838 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4839 SpdyFramer::StateToString(
4840 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4841 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4842 SpdyFramer::StateToString(
4843 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4844 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4845 SpdyFramer::StateToString(
4846 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4847 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4848 SpdyFramer::StateToString(
4849 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4850 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4851 SpdyFramer::StateToString(
4852 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4853 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4854 SpdyFramer::StateToString(
4855 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4856 EXPECT_STREQ("UNKNOWN_STATE",
4857 SpdyFramer::StateToString(
4858 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4861 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4862 EXPECT_STREQ("NO_ERROR",
4863 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4864 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4865 SpdyFramer::ErrorCodeToString(
4866 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4867 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4868 SpdyFramer::ErrorCodeToString(
4869 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4870 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4871 SpdyFramer::ErrorCodeToString(
4872 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4873 EXPECT_STREQ("UNSUPPORTED_VERSION",
4874 SpdyFramer::ErrorCodeToString(
4875 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4876 EXPECT_STREQ("DECOMPRESS_FAILURE",
4877 SpdyFramer::ErrorCodeToString(
4878 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4879 EXPECT_STREQ("COMPRESS_FAILURE",
4880 SpdyFramer::ErrorCodeToString(
4881 SpdyFramer::SPDY_COMPRESS_FAILURE));
4882 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4883 SpdyFramer::ErrorCodeToString(
4884 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4885 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4886 SpdyFramer::ErrorCodeToString(
4887 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4888 EXPECT_STREQ("UNKNOWN_ERROR",
4889 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4892 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4893 EXPECT_STREQ("INVALID",
4894 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4895 EXPECT_STREQ("PROTOCOL_ERROR",
4896 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4897 EXPECT_STREQ("INVALID_STREAM",
4898 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4899 EXPECT_STREQ("REFUSED_STREAM",
4900 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4901 EXPECT_STREQ("UNSUPPORTED_VERSION",
4902 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4903 EXPECT_STREQ("CANCEL",
4904 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4905 EXPECT_STREQ("INTERNAL_ERROR",
4906 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4907 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4908 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4909 EXPECT_STREQ("UNKNOWN_STATUS",
4910 SpdyFramer::StatusCodeToString(-1));
4913 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4914 EXPECT_STREQ("DATA",
4915 SpdyFramer::FrameTypeToString(DATA));
4916 EXPECT_STREQ("SYN_STREAM",
4917 SpdyFramer::FrameTypeToString(SYN_STREAM));
4918 EXPECT_STREQ("SYN_REPLY",
4919 SpdyFramer::FrameTypeToString(SYN_REPLY));
4920 EXPECT_STREQ("RST_STREAM",
4921 SpdyFramer::FrameTypeToString(RST_STREAM));
4922 EXPECT_STREQ("SETTINGS",
4923 SpdyFramer::FrameTypeToString(SETTINGS));
4924 EXPECT_STREQ("PING",
4925 SpdyFramer::FrameTypeToString(PING));
4926 EXPECT_STREQ("GOAWAY",
4927 SpdyFramer::FrameTypeToString(GOAWAY));
4928 EXPECT_STREQ("HEADERS",
4929 SpdyFramer::FrameTypeToString(HEADERS));
4930 EXPECT_STREQ("WINDOW_UPDATE",
4931 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4932 EXPECT_STREQ("PUSH_PROMISE",
4933 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4934 EXPECT_STREQ("CREDENTIAL",
4935 SpdyFramer::FrameTypeToString(CREDENTIAL));
4936 EXPECT_STREQ("CONTINUATION",
4937 SpdyFramer::FrameTypeToString(CONTINUATION));
4940 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4941 if (IsHttp2()) {
4942 // TODO(hkhalil): catch probable HTTP response in HTTP/2?
4943 return;
4946 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4947 SpdyFramer framer(spdy_version_);
4948 framer.set_visitor(&visitor);
4950 EXPECT_CALL(visitor, OnError(_));
4951 framer.ProcessInput("HTTP/1.1", 8);
4952 EXPECT_TRUE(framer.probable_http_response());
4953 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4954 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4955 << SpdyFramer::ErrorCodeToString(framer.error_code());
4958 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4959 SpdyFramer framer(spdy_version_);
4960 framer.set_visitor(&visitor);
4962 EXPECT_CALL(visitor, OnError(_));
4963 framer.ProcessInput("HTTP/1.0", 8);
4964 EXPECT_TRUE(framer.probable_http_response());
4965 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4966 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4967 << SpdyFramer::ErrorCodeToString(framer.error_code());
4971 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4972 if (spdy_version_ > SPDY3) {
4973 return;
4976 uint8 flags = 0;
4977 do {
4978 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4980 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4981 SpdyFramer framer(spdy_version_);
4982 framer.set_visitor(&visitor);
4984 SpdyDataIR data_ir(1, "hello");
4985 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4986 SetFrameFlags(frame.get(), flags, spdy_version_);
4988 if (flags & ~DATA_FLAG_FIN) {
4989 EXPECT_CALL(visitor, OnError(_));
4990 } else {
4991 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4992 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4993 if (flags & DATA_FLAG_FIN) {
4994 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4998 framer.ProcessInput(frame->data(), frame->size());
4999 if (flags & ~DATA_FLAG_FIN) {
5000 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5001 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
5002 framer.error_code())
5003 << SpdyFramer::ErrorCodeToString(framer.error_code());
5004 } else {
5005 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5006 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5007 << SpdyFramer::ErrorCodeToString(framer.error_code());
5009 } while (++flags != 0);
5012 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
5013 if (spdy_version_ <= SPDY3) {
5014 return;
5017 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
5018 DATA_FLAG_PADDED;
5020 uint8 flags = 0;
5021 do {
5022 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5024 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5025 SpdyFramer framer(spdy_version_);
5026 framer.set_visitor(&visitor);
5028 SpdyDataIR data_ir(1, "hello");
5029 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
5030 SetFrameFlags(frame.get(), flags, spdy_version_);
5032 if (flags & ~valid_data_flags) {
5033 EXPECT_CALL(visitor, OnError(_));
5034 } else {
5035 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
5036 if (flags & DATA_FLAG_PADDED) {
5037 // The first byte of payload is parsed as padding length.
5038 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
5039 // Expect Error since the frame ends prematurely.
5040 EXPECT_CALL(visitor, OnError(_));
5041 } else {
5042 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
5043 if (flags & DATA_FLAG_FIN) {
5044 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5049 framer.ProcessInput(frame->data(), frame->size());
5050 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
5051 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5052 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
5053 << SpdyFramer::ErrorCodeToString(framer.error_code());
5054 } else {
5055 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5056 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5057 << SpdyFramer::ErrorCodeToString(framer.error_code());
5059 } while (++flags != 0);
5062 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
5063 if (!IsSpdy2() && !IsSpdy3()) {
5064 // SYN_STREAM not supported in SPDY>3
5065 return;
5067 uint8 flags = 0;
5068 do {
5069 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5071 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5072 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5073 SpdyFramer framer(spdy_version_);
5074 framer.set_visitor(&visitor);
5075 framer.set_debug_visitor(&debug_visitor);
5077 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
5079 SpdySynStreamIR syn_stream(8);
5080 syn_stream.set_associated_to_stream_id(3);
5081 syn_stream.set_priority(1);
5082 syn_stream.SetHeader("foo", "bar");
5083 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5084 SetFrameFlags(frame.get(), flags, spdy_version_);
5086 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5087 EXPECT_CALL(visitor, OnError(_));
5088 } else {
5089 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
5090 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
5091 flags & CONTROL_FLAG_UNIDIRECTIONAL));
5092 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
5093 .WillRepeatedly(testing::Return(true));
5094 if (flags & DATA_FLAG_FIN) {
5095 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5096 } else {
5097 // Do not close the stream if we are expecting a CONTINUATION frame.
5098 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5102 framer.ProcessInput(frame->data(), frame->size());
5103 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5104 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5105 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5106 framer.error_code())
5107 << SpdyFramer::ErrorCodeToString(framer.error_code());
5108 } else {
5109 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5110 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5111 << SpdyFramer::ErrorCodeToString(framer.error_code());
5113 } while (++flags != 0);
5116 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
5117 if (!IsSpdy2() && !IsSpdy3()) {
5118 // SYN_REPLY not supported in SPDY>3
5119 return;
5121 uint8 flags = 0;
5122 do {
5123 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5125 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5126 SpdyFramer framer(spdy_version_);
5127 framer.set_visitor(&visitor);
5129 SpdySynReplyIR syn_reply(37);
5130 syn_reply.SetHeader("foo", "bar");
5131 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5132 SetFrameFlags(frame.get(), flags, spdy_version_);
5134 if (flags & ~CONTROL_FLAG_FIN) {
5135 EXPECT_CALL(visitor, OnError(_));
5136 } else {
5137 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5138 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5139 .WillRepeatedly(testing::Return(true));
5140 if (flags & DATA_FLAG_FIN) {
5141 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5145 framer.ProcessInput(frame->data(), frame->size());
5146 if (flags & ~CONTROL_FLAG_FIN) {
5147 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5148 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5149 framer.error_code())
5150 << SpdyFramer::ErrorCodeToString(framer.error_code());
5151 } else {
5152 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5153 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5154 << SpdyFramer::ErrorCodeToString(framer.error_code());
5156 } while (++flags != 0);
5159 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5160 uint8 flags = 0;
5161 do {
5162 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5164 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5165 SpdyFramer framer(spdy_version_);
5166 framer.set_visitor(&visitor);
5168 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5169 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5170 SetFrameFlags(frame.get(), flags, spdy_version_);
5172 if (flags != 0) {
5173 EXPECT_CALL(visitor, OnError(_));
5174 } else {
5175 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5178 framer.ProcessInput(frame->data(), frame->size());
5179 if (flags != 0) {
5180 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5181 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5182 framer.error_code())
5183 << SpdyFramer::ErrorCodeToString(framer.error_code());
5184 } else {
5185 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5186 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5187 << SpdyFramer::ErrorCodeToString(framer.error_code());
5189 } while (++flags != 0);
5192 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5193 if (spdy_version_ > SPDY3) { return; }
5194 uint8 flags = 0;
5195 do {
5196 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5198 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5199 SpdyFramer framer(spdy_version_);
5200 framer.set_visitor(&visitor);
5202 SpdySettingsIR settings_ir;
5203 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5204 false,
5205 false,
5206 54321);
5207 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5208 SetFrameFlags(frame.get(), flags, spdy_version_);
5210 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5211 EXPECT_CALL(visitor, OnError(_));
5212 } else {
5213 EXPECT_CALL(visitor, OnSettings(
5214 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5215 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5216 SETTINGS_FLAG_NONE, 54321));
5217 EXPECT_CALL(visitor, OnSettingsEnd());
5220 framer.ProcessInput(frame->data(), frame->size());
5221 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5222 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5223 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5224 framer.error_code())
5225 << SpdyFramer::ErrorCodeToString(framer.error_code());
5226 } else {
5227 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5228 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5229 << SpdyFramer::ErrorCodeToString(framer.error_code());
5231 } while (++flags != 0);
5234 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5235 if (spdy_version_ <= SPDY3) { return; }
5236 uint8 flags = 0;
5237 do {
5238 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5240 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5241 SpdyFramer framer(spdy_version_);
5242 framer.set_visitor(&visitor);
5244 SpdySettingsIR settings_ir;
5245 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5246 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5247 SetFrameFlags(frame.get(), flags, spdy_version_);
5249 if (flags != 0) {
5250 EXPECT_CALL(visitor, OnError(_));
5251 } else {
5252 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5253 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5254 EXPECT_CALL(visitor, OnSettingsEnd());
5257 framer.ProcessInput(frame->data(), frame->size());
5258 if (flags & ~SETTINGS_FLAG_ACK) {
5259 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5260 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5261 framer.error_code())
5262 << SpdyFramer::ErrorCodeToString(framer.error_code());
5263 } else if (flags & SETTINGS_FLAG_ACK) {
5264 // The frame is invalid because ACK frames should have no payload.
5265 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5266 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5267 framer.error_code())
5268 << SpdyFramer::ErrorCodeToString(framer.error_code());
5269 } else {
5270 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5271 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5272 << SpdyFramer::ErrorCodeToString(framer.error_code());
5274 } while (++flags != 0);
5277 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5278 uint8 flags = 0;
5279 do {
5280 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5282 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5283 SpdyFramer framer(spdy_version_);
5284 framer.set_visitor(&visitor);
5286 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5287 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5288 SetFrameFlags(frame.get(), flags, spdy_version_);
5290 if (flags != 0) {
5291 EXPECT_CALL(visitor, OnError(_));
5292 } else {
5293 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5296 framer.ProcessInput(frame->data(), frame->size());
5297 if (flags != 0) {
5298 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5299 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5300 framer.error_code())
5301 << SpdyFramer::ErrorCodeToString(framer.error_code());
5302 } else {
5303 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5304 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5305 << SpdyFramer::ErrorCodeToString(framer.error_code());
5307 } while (++flags != 0);
5310 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5311 uint8 flags = 0;
5312 do {
5313 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5315 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5316 SpdyFramer framer(spdy_version_);
5317 framer.set_visitor(&visitor);
5319 SpdyHeadersIR headers_ir(57);
5320 if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) {
5321 headers_ir.set_priority(3);
5322 headers_ir.set_has_priority(true);
5323 headers_ir.set_parent_stream_id(5);
5324 headers_ir.set_exclusive(true);
5326 headers_ir.SetHeader("foo", "bar");
5327 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5328 uint8 set_flags = flags;
5329 if (IsHttp2()) {
5330 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5331 // and implement framing.
5332 set_flags &= ~HEADERS_FLAG_PADDED;
5334 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5336 if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
5337 EXPECT_CALL(visitor, OnError(_));
5338 } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
5339 HEADERS_FLAG_END_HEADERS |
5340 HEADERS_FLAG_END_SEGMENT |
5341 HEADERS_FLAG_PADDED |
5342 HEADERS_FLAG_PRIORITY)) {
5343 EXPECT_CALL(visitor, OnError(_));
5344 } else {
5345 // Expected callback values
5346 SpdyStreamId stream_id = 57;
5347 bool has_priority = false;
5348 SpdyPriority priority = 0;
5349 SpdyStreamId parent_stream_id = 0;
5350 bool exclusive = false;
5351 bool fin = flags & CONTROL_FLAG_FIN;
5352 bool end = !IsHttp2() || (flags & HEADERS_FLAG_END_HEADERS);
5353 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5354 has_priority = true;
5355 priority = 3;
5356 parent_stream_id = 5;
5357 exclusive = true;
5359 EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority,
5360 parent_stream_id, exclusive, fin, end));
5361 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5362 .WillRepeatedly(testing::Return(true));
5363 if (flags & DATA_FLAG_FIN &&
5364 (!IsHttp2() || flags & HEADERS_FLAG_END_HEADERS)) {
5365 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5366 } else {
5367 // Do not close the stream if we are expecting a CONTINUATION frame.
5368 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5372 framer.ProcessInput(frame->data(), frame->size());
5373 if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
5374 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5375 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5376 framer.error_code())
5377 << SpdyFramer::ErrorCodeToString(framer.error_code());
5378 } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
5379 HEADERS_FLAG_END_HEADERS |
5380 HEADERS_FLAG_END_SEGMENT |
5381 HEADERS_FLAG_PADDED |
5382 HEADERS_FLAG_PRIORITY)) {
5383 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5384 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5385 framer.error_code())
5386 << SpdyFramer::ErrorCodeToString(framer.error_code());
5387 } else if (IsHttp2() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5388 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5389 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5390 << SpdyFramer::ErrorCodeToString(framer.error_code());
5391 } else {
5392 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5393 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5394 << SpdyFramer::ErrorCodeToString(framer.error_code());
5396 } while (++flags != 0);
5399 TEST_P(SpdyFramerTest, PingFrameFlags) {
5400 uint8 flags = 0;
5401 do {
5402 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5404 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5405 SpdyFramer framer(spdy_version_);
5406 framer.set_visitor(&visitor);
5408 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5409 SetFrameFlags(frame.get(), flags, spdy_version_);
5411 if (spdy_version_ > SPDY3 &&
5412 flags == PING_FLAG_ACK) {
5413 EXPECT_CALL(visitor, OnPing(42, true));
5414 } else if (flags == 0) {
5415 EXPECT_CALL(visitor, OnPing(42, false));
5416 } else {
5417 EXPECT_CALL(visitor, OnError(_));
5420 framer.ProcessInput(frame->data(), frame->size());
5421 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5422 flags == 0) {
5423 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5424 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5425 << SpdyFramer::ErrorCodeToString(framer.error_code());
5426 } else {
5427 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5428 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5429 framer.error_code())
5430 << SpdyFramer::ErrorCodeToString(framer.error_code());
5432 } while (++flags != 0);
5435 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5436 uint8 flags = 0;
5437 do {
5438 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5440 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5441 SpdyFramer framer(spdy_version_);
5442 framer.set_visitor(&visitor);
5444 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5445 SpdyWindowUpdateIR(4, 1024)));
5446 SetFrameFlags(frame.get(), flags, spdy_version_);
5448 if (flags != 0) {
5449 EXPECT_CALL(visitor, OnError(_));
5450 } else {
5451 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5454 framer.ProcessInput(frame->data(), frame->size());
5455 if (flags != 0) {
5456 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5457 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5458 framer.error_code())
5459 << SpdyFramer::ErrorCodeToString(framer.error_code());
5460 } else {
5461 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5462 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5463 << SpdyFramer::ErrorCodeToString(framer.error_code());
5465 } while (++flags != 0);
5468 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5469 if (spdy_version_ <= SPDY3) {
5470 return;
5473 uint8 flags = 0;
5474 do {
5475 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5477 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5478 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5479 SpdyFramer framer(spdy_version_);
5480 framer.set_visitor(&visitor);
5481 framer.set_debug_visitor(&debug_visitor);
5483 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5485 SpdyPushPromiseIR push_promise(42, 57);
5486 push_promise.SetHeader("foo", "bar");
5487 scoped_ptr<SpdySerializedFrame> frame(
5488 framer.SerializePushPromise(push_promise));
5489 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5490 // and implement framing.
5491 SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
5493 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5494 EXPECT_CALL(visitor, OnError(_));
5495 } else {
5496 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5497 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5498 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5499 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5500 .WillRepeatedly(testing::Return(true));
5503 framer.ProcessInput(frame->data(), frame->size());
5504 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5505 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5506 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5507 framer.error_code())
5508 << SpdyFramer::ErrorCodeToString(framer.error_code());
5509 } else {
5510 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5511 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5512 << SpdyFramer::ErrorCodeToString(framer.error_code());
5514 } while (++flags != 0);
5517 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5518 if (spdy_version_ <= SPDY3) {
5519 return;
5522 uint8 flags = 0;
5523 do {
5524 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5526 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5527 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5528 SpdyFramer framer(spdy_version_);
5529 framer.set_visitor(&visitor);
5530 framer.set_debug_visitor(&debug_visitor);
5532 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5533 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5534 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false, false, false));
5535 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5536 .WillRepeatedly(testing::Return(true));
5538 SpdyHeadersIR headers_ir(42);
5539 headers_ir.SetHeader("foo", "bar");
5540 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5541 SetFrameFlags(frame0.get(), 0, spdy_version_);
5543 SpdyContinuationIR continuation(42);
5544 continuation.SetHeader("foo", "bar");
5545 scoped_ptr<SpdySerializedFrame> frame(
5546 framer.SerializeContinuation(continuation));
5547 SetFrameFlags(frame.get(), flags, spdy_version_);
5549 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5550 EXPECT_CALL(visitor, OnError(_));
5551 } else {
5552 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5553 EXPECT_CALL(visitor, OnContinuation(42,
5554 flags & HEADERS_FLAG_END_HEADERS));
5555 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5556 .WillRepeatedly(testing::Return(true));
5559 framer.ProcessInput(frame0->data(), frame0->size());
5560 framer.ProcessInput(frame->data(), frame->size());
5561 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5562 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5563 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5564 framer.error_code())
5565 << SpdyFramer::ErrorCodeToString(framer.error_code());
5566 } else {
5567 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5568 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5569 << SpdyFramer::ErrorCodeToString(framer.error_code());
5571 } while (++flags != 0);
5574 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5576 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5578 TEST_P(SpdyFramerTest, EmptySynStream) {
5579 if (!IsSpdy2() && !IsSpdy3()) {
5580 // SYN_STREAM not supported in SPDY>3.
5581 return;
5583 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5584 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5585 SpdyFramer framer(spdy_version_);
5586 framer.set_visitor(&visitor);
5587 framer.set_debug_visitor(&debug_visitor);
5589 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5591 SpdySynStreamIR syn_stream(1);
5592 syn_stream.set_priority(1);
5593 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5594 // Adjust size to remove the header block.
5595 SetFrameLength(
5596 frame.get(),
5597 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5598 spdy_version_);
5600 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5601 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5602 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5604 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5605 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5606 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5607 << SpdyFramer::ErrorCodeToString(framer.error_code());
5610 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5611 const uint32 kId = 0x020304;
5612 const uint32 kFlags = 0x01;
5613 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5615 SettingsFlagsAndId id_and_flags =
5616 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5617 EXPECT_EQ(kId, id_and_flags.id());
5618 EXPECT_EQ(kFlags, id_and_flags.flags());
5619 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5622 // Test handling of a RST_STREAM with out-of-bounds status codes.
5623 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5624 const unsigned char kRstStreamStatusTooLow = 0x00;
5625 const unsigned char kRstStreamStatusTooHigh = 0xff;
5626 const unsigned char kV3RstStreamInvalid[] = {
5627 0x80, spdy_version_ch_, 0x00, 0x03,
5628 0x00, 0x00, 0x00, 0x08,
5629 0x00, 0x00, 0x00, 0x01,
5630 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5632 const unsigned char kH2RstStreamInvalid[] = {
5633 0x00, 0x00, 0x04, 0x03,
5634 0x00, 0x00, 0x00, 0x00,
5635 0x01, 0x00, 0x00, 0x00,
5636 kRstStreamStatusTooLow
5639 const unsigned char kV3RstStreamNumStatusCodes[] = {
5640 0x80, spdy_version_ch_, 0x00, 0x03,
5641 0x00, 0x00, 0x00, 0x08,
5642 0x00, 0x00, 0x00, 0x01,
5643 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5645 const unsigned char kH2RstStreamNumStatusCodes[] = {
5646 0x00, 0x00, 0x04, 0x03,
5647 0x00, 0x00, 0x00, 0x00,
5648 0x01, 0x00, 0x00, 0x00,
5649 kRstStreamStatusTooHigh
5652 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5653 SpdyFramer framer(spdy_version_);
5654 framer.set_visitor(&visitor);
5656 if (IsHttp2()) {
5657 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5658 framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
5659 arraysize(kH2RstStreamInvalid));
5660 } else {
5661 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5662 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5663 arraysize(kV3RstStreamInvalid));
5665 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5666 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5667 << SpdyFramer::ErrorCodeToString(framer.error_code());
5670 framer.Reset();
5672 if (IsHttp2()) {
5673 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5674 framer.ProcessInput(
5675 reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
5676 arraysize(kH2RstStreamNumStatusCodes));
5677 } else {
5678 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5679 framer.ProcessInput(
5680 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5681 arraysize(kV3RstStreamNumStatusCodes));
5683 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5684 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5685 << SpdyFramer::ErrorCodeToString(framer.error_code());
5688 // Test handling of GOAWAY frames with out-of-bounds status code.
5689 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5690 if (spdy_version_ <= SPDY2) {
5691 return;
5693 SpdyFramer framer(spdy_version_);
5695 const unsigned char kV3FrameData[] = {
5696 0x80, spdy_version_ch_, 0x00, 0x07,
5697 0x00, 0x00, 0x00, 0x08,
5698 0x00, 0x00, 0x00, 0x01, // Stream Id
5699 0xff, 0xff, 0xff, 0xff, // Status
5701 const unsigned char kH2FrameData[] = {
5702 0x00, 0x00, 0x0a, 0x07,
5703 0x00, 0x00, 0x00, 0x00,
5704 0x00, 0x00, 0x00, 0x00, // Stream id
5705 0x01, 0xff, 0xff, 0xff, // Status
5706 0xff, 0x47, 0x41, // Opaque Description
5708 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5709 framer.set_visitor(&visitor);
5711 if (IsSpdy3()) {
5712 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5713 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5714 arraysize(kV3FrameData));
5715 } else {
5716 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5717 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
5718 arraysize(kH2FrameData));
5720 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5721 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5722 << SpdyFramer::ErrorCodeToString(framer.error_code());
5725 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5726 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5727 const unsigned char kV2FrameData[] = {
5728 0x80, spdy_version_ch_, 0x00, 0x07,
5729 0x00, 0x00, 0x00, 0x04,
5730 0xff, 0xff, 0xff, 0xff,
5732 const unsigned char kV3FrameData[] = {
5733 0x80, spdy_version_ch_, 0x00, 0x07,
5734 0x00, 0x00, 0x00, 0x08,
5735 0xff, 0xff, 0xff, 0xff,
5736 0x00, 0x00, 0x00, 0x00,
5738 const unsigned char kH2FrameData[] = {
5739 0x00, 0x00, 0x08, 0x07,
5740 0x00, 0x00, 0x00, 0x00,
5741 0x00, 0xff, 0xff, 0xff,
5742 0xff, 0x00, 0x00, 0x00,
5743 0x00,
5746 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5747 SpdyFramer framer(spdy_version_);
5748 framer.set_visitor(&visitor);
5750 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5751 if (IsSpdy2()) {
5752 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5753 arraysize(kV2FrameData));
5754 } else if (IsSpdy3()) {
5755 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5756 arraysize(kV3FrameData));
5757 } else {
5758 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
5759 arraysize(kH2FrameData));
5761 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5762 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5763 << SpdyFramer::ErrorCodeToString(framer.error_code());
5766 TEST_P(SpdyFramerTest, OnBlocked) {
5767 if (spdy_version_ <= SPDY3) {
5768 return;
5771 const SpdyStreamId kStreamId = 0;
5773 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5774 SpdyFramer framer(spdy_version_);
5775 framer.set_visitor(&visitor);
5777 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5779 SpdyBlockedIR blocked_ir(0);
5780 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5781 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5783 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5784 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5785 << SpdyFramer::ErrorCodeToString(framer.error_code());
5788 TEST_P(SpdyFramerTest, OnAltSvc) {
5789 if (spdy_version_ <= SPDY3) {
5790 return;
5793 const SpdyStreamId kStreamId = 1;
5795 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5796 SpdyFramer framer(spdy_version_);
5797 framer.set_visitor(&visitor);
5799 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5800 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5801 42, 0.2);
5802 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5803 altsvc_vector.push_back(altsvc1);
5804 altsvc_vector.push_back(altsvc2);
5805 EXPECT_CALL(visitor,
5806 OnAltSvc(kStreamId, StringPiece("o_r|g!n"), altsvc_vector));
5808 SpdyAltSvcIR altsvc_ir(1);
5809 altsvc_ir.set_origin("o_r|g!n");
5810 altsvc_ir.add_altsvc(altsvc1);
5811 altsvc_ir.add_altsvc(altsvc2);
5812 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5813 framer.ProcessInput(frame->data(), frame->size());
5815 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5816 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5817 << SpdyFramer::ErrorCodeToString(framer.error_code());
5820 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5821 if (spdy_version_ <= SPDY3) {
5822 return;
5825 const SpdyStreamId kStreamId = 1;
5827 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5828 SpdyFramer framer(spdy_version_);
5829 framer.set_visitor(&visitor);
5831 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5832 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5833 42, 0.2);
5834 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5835 altsvc_vector.push_back(altsvc1);
5836 altsvc_vector.push_back(altsvc2);
5837 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece(""), altsvc_vector));
5839 SpdyAltSvcIR altsvc_ir(1);
5840 altsvc_ir.add_altsvc(altsvc1);
5841 altsvc_ir.add_altsvc(altsvc2);
5842 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5843 framer.ProcessInput(frame->data(), frame->size());
5845 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5846 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5847 << SpdyFramer::ErrorCodeToString(framer.error_code());
5850 TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
5851 if (spdy_version_ <= SPDY3) {
5852 return;
5855 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5856 SpdyFramer framer(spdy_version_);
5857 framer.set_visitor(&visitor);
5859 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
5861 SpdyAltSvcIR altsvc_ir(1);
5862 altsvc_ir.set_origin("o1");
5863 altsvc_ir.add_altsvc(
5864 SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0));
5865 altsvc_ir.add_altsvc(
5866 SpdyAltSvcWireFormat::AlternativeService("", "h1", 443, 10, 1.0));
5867 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5868 framer.ProcessInput(frame->data(), frame->size());
5870 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5871 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
5872 << SpdyFramer::ErrorCodeToString(framer.error_code());
5875 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5876 if (spdy_version_ <= SPDY3) {
5877 return;
5880 const SpdyStreamId kStreamId = 1;
5882 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5883 SpdyFramer framer(spdy_version_);
5884 framer.set_visitor(&visitor);
5886 SpdyAltSvcWireFormat::AlternativeService altsvc("pid", "h1", 443, 10, 1.0);
5887 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5888 altsvc_vector.push_back(altsvc);
5889 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece("o1"), altsvc_vector));
5891 SpdyAltSvcIR altsvc_ir(1);
5892 altsvc_ir.set_origin("o1");
5893 altsvc_ir.add_altsvc(altsvc);
5894 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5895 framer.ProcessInput(frame->data(), frame->size());
5897 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5898 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5899 << SpdyFramer::ErrorCodeToString(framer.error_code());
5902 // Tests handling of ALTSVC frames delivered in small chunks.
5903 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5904 if (spdy_version_ <= SPDY3) {
5905 return;
5908 SpdyFramer framer(spdy_version_);
5909 SpdyAltSvcIR altsvc_ir(1);
5910 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5911 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5912 42, 0.2);
5913 altsvc_ir.add_altsvc(altsvc1);
5914 altsvc_ir.add_altsvc(altsvc2);
5916 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5917 TestSpdyVisitor visitor(spdy_version_);
5918 visitor.use_compression_ = false;
5920 // Read data in small chunks.
5921 size_t framed_data = 0;
5922 size_t unframed_data = control_frame->size();
5923 size_t kReadChunkSize = 5; // Read five bytes at a time.
5924 while (unframed_data > 0) {
5925 size_t to_read = std::min(kReadChunkSize, unframed_data);
5926 visitor.SimulateInFramer(
5927 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5928 to_read);
5929 unframed_data -= to_read;
5930 framed_data += to_read;
5932 EXPECT_EQ(0, visitor.error_count_);
5933 EXPECT_EQ(1, visitor.altsvc_count_);
5934 ASSERT_EQ(2u, visitor.test_altsvc_ir_.altsvc_vector().size());
5935 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[0] == altsvc1);
5936 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[1] == altsvc2);
5939 // Tests handling of PRIORITY frames.
5940 TEST_P(SpdyFramerTest, ReadPriority) {
5941 if (spdy_version_ <= SPDY3) {
5942 return;
5944 SpdyFramer framer(spdy_version_);
5945 SpdyPriorityIR priority(3, 1, 255, false);
5946 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5947 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5948 framer.set_visitor(&visitor);
5949 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5950 framer.ProcessInput(frame->data(), frame->size());
5952 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5953 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5954 << SpdyFramer::ErrorCodeToString(framer.error_code());
5955 // TODO(mlavan): once we actually maintain a priority tree,
5956 // check that state is adjusted correctly.
5959 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5960 if (spdy_version_ <= SPDY3) {
5961 return;
5963 SpdyFramer framer(spdy_version_);
5965 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5966 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5967 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5968 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5969 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5970 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5971 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5972 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5974 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5975 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5976 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5977 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5978 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5979 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5980 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5981 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5982 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5983 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5984 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5985 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5986 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5987 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5988 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5991 // Tests handling of PRIORITY frame with incorrect size.
5992 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5993 if (spdy_version_ <= SPDY3) {
5994 return;
5997 // PRIORITY frame of size 4, which isn't correct.
5998 const unsigned char kFrameData[] = {
5999 0x00, 0x00, 0x04, 0x02, 0x00,
6000 0x00, 0x00, 0x00, 0x03,
6001 0x00, 0x00, 0x00, 0x01,
6004 TestSpdyVisitor visitor(spdy_version_);
6005 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
6007 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
6008 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
6009 visitor.framer_.error_code())
6010 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
6013 } // namespace test
6015 } // namespace net