Port Android relocation packer to chromium build
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blobb87748b23f738efce6ed70ab67f48f5e06c59a2e
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <algorithm>
6 #include <iostream>
7 #include <limits>
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
21 using std::string;
22 using testing::_;
24 namespace net {
26 namespace test {
28 static const size_t kMaxDecompressedSize = 1024;
30 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
31 public:
32 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
33 SpdyFrameType type,
34 size_t payload_len,
35 size_t frame_len));
37 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
38 SpdyFrameType type,
39 size_t frame_len));
42 class SpdyFramerTestUtil {
43 public:
44 // Decompress a single frame using the decompression context held by
45 // the SpdyFramer. The implemention is meant for use only in tests
46 // and will CHECK fail if the input is anything other than a single,
47 // well-formed compressed frame.
49 // Returns a new decompressed SpdyFrame.
50 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
51 SpdyFramer* framer, const SpdyFrameType& frame) {
52 DecompressionVisitor visitor(framer->protocol_version());
53 framer->set_visitor(&visitor);
54 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
55 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
56 framer->set_visitor(NULL);
58 char* buffer = visitor.ReleaseBuffer();
59 CHECK(buffer != NULL);
60 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
61 SetFrameLength(decompressed_frame,
62 visitor.size() - framer->GetControlFrameHeaderSize(),
63 framer->protocol_version());
64 return decompressed_frame;
67 class DecompressionVisitor : public SpdyFramerVisitorInterface {
68 public:
69 explicit DecompressionVisitor(SpdyMajorVersion version)
70 : version_(version), size_(0), finished_(false) {}
72 void ResetBuffer() {
73 CHECK(buffer_.get() == NULL);
74 CHECK_EQ(0u, size_);
75 CHECK(!finished_);
76 buffer_.reset(new char[kMaxDecompressedSize]);
79 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
80 void OnDataFrameHeader(SpdyStreamId stream_id,
81 size_t length,
82 bool fin) override {
83 LOG(FATAL) << "Unexpected data frame header";
85 void OnStreamFrameData(SpdyStreamId stream_id,
86 const char* data,
87 size_t len,
88 bool fin) override {
89 LOG(FATAL);
92 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
93 LOG(FATAL);
96 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
97 const char* header_data,
98 size_t len) override {
99 CHECK(buffer_.get() != NULL);
100 CHECK_GE(kMaxDecompressedSize, size_ + len);
101 CHECK(!finished_);
102 if (len != 0) {
103 memcpy(buffer_.get() + size_, header_data, len);
104 size_ += len;
105 } else {
106 // Done.
107 finished_ = true;
109 return true;
112 void OnSynStream(SpdyStreamId stream_id,
113 SpdyStreamId associated_stream_id,
114 SpdyPriority priority,
115 bool fin,
116 bool unidirectional) override {
117 SpdyFramer framer(version_);
118 framer.set_enable_compression(false);
119 SpdySynStreamIR syn_stream(stream_id);
120 syn_stream.set_associated_to_stream_id(associated_stream_id);
121 syn_stream.set_priority(priority);
122 syn_stream.set_fin(fin);
123 syn_stream.set_unidirectional(unidirectional);
124 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
125 ResetBuffer();
126 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
127 size_ += framer.GetSynStreamMinimumSize();
130 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
131 SpdyFramer framer(version_);
132 framer.set_enable_compression(false);
133 SpdyHeadersIR headers(stream_id);
134 headers.set_fin(fin);
135 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
136 ResetBuffer();
137 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
138 size_ += framer.GetSynStreamMinimumSize();
141 void OnRstStream(SpdyStreamId stream_id,
142 SpdyRstStreamStatus status) override {
143 LOG(FATAL);
145 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
146 LOG(FATAL);
148 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
149 void OnSettingsEnd() override { LOG(FATAL); }
150 void OnGoAway(SpdyStreamId last_accepted_stream_id,
151 SpdyGoAwayStatus status) override {
152 LOG(FATAL);
155 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
156 SpdyPriority priority, bool fin, bool end) override {
157 SpdyFramer framer(version_);
158 framer.set_enable_compression(false);
159 SpdyHeadersIR headers(stream_id);
160 headers.set_has_priority(has_priority);
161 if (headers.has_priority()) {
162 headers.set_priority(priority);
164 headers.set_fin(fin);
165 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
166 ResetBuffer();
167 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
168 size_ += framer.GetHeadersMinimumSize();
171 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
172 LOG(FATAL);
175 void OnPushPromise(SpdyStreamId stream_id,
176 SpdyStreamId promised_stream_id,
177 bool end) override {
178 SpdyFramer framer(version_);
179 framer.set_enable_compression(false);
180 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
181 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
182 ResetBuffer();
183 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
184 size_ += framer.GetPushPromiseMinimumSize();
187 void OnContinuation(SpdyStreamId stream_id, bool end) override {
188 LOG(FATAL);
191 void OnPriority(SpdyStreamId stream_id,
192 SpdyStreamId parent_stream_id,
193 uint8 weight,
194 bool exclusive) override {
195 // Do nothing.
198 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
199 LOG(FATAL);
200 return false;
203 char* ReleaseBuffer() {
204 CHECK(finished_);
205 return buffer_.release();
208 void OnWindowUpdate(SpdyStreamId stream_id,
209 uint32 delta_window_size) override {
210 LOG(FATAL);
213 size_t size() const {
214 CHECK(finished_);
215 return size_;
218 private:
219 SpdyMajorVersion version_;
220 scoped_ptr<char[]> buffer_;
221 size_t size_;
222 bool finished_;
224 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
227 private:
228 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
231 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
232 public SpdyFramerDebugVisitorInterface {
233 public:
234 // This is larger than our max frame size because header blocks that
235 // are too long can spill over into CONTINUATION frames.
236 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
238 explicit TestSpdyVisitor(SpdyMajorVersion version)
239 : framer_(version),
240 use_compression_(false),
241 error_count_(0),
242 syn_frame_count_(0),
243 syn_reply_frame_count_(0),
244 headers_frame_count_(0),
245 push_promise_frame_count_(0),
246 goaway_count_(0),
247 setting_count_(0),
248 settings_ack_sent_(0),
249 settings_ack_received_(0),
250 continuation_count_(0),
251 altsvc_count_(0),
252 priority_count_(0),
253 test_altsvc_ir_(0),
254 on_unknown_frame_result_(false),
255 last_window_update_stream_(0),
256 last_window_update_delta_(0),
257 last_push_promise_stream_(0),
258 last_push_promise_promised_stream_(0),
259 data_bytes_(0),
260 fin_frame_count_(0),
261 fin_opaque_data_(),
262 fin_flag_count_(0),
263 zero_length_data_frame_count_(0),
264 control_frame_header_data_count_(0),
265 zero_length_control_frame_header_data_count_(0),
266 data_frame_count_(0),
267 last_payload_len_(0),
268 last_frame_len_(0),
269 header_buffer_(new char[kDefaultHeaderBufferSize]),
270 header_buffer_length_(0),
271 header_buffer_size_(kDefaultHeaderBufferSize),
272 header_stream_id_(static_cast<SpdyStreamId>(-1)),
273 header_control_type_(DATA),
274 header_buffer_valid_(false) {}
276 void OnError(SpdyFramer* f) override {
277 LOG(INFO) << "SpdyFramer Error: "
278 << SpdyFramer::ErrorCodeToString(f->error_code());
279 ++error_count_;
282 void OnDataFrameHeader(SpdyStreamId stream_id,
283 size_t length,
284 bool fin) override {
285 ++data_frame_count_;
286 header_stream_id_ = stream_id;
289 void OnStreamFrameData(SpdyStreamId stream_id,
290 const char* data,
291 size_t len,
292 bool fin) override {
293 EXPECT_EQ(header_stream_id_, stream_id);
294 if (len == 0)
295 ++zero_length_data_frame_count_;
297 data_bytes_ += len;
298 LOG(INFO) << "OnStreamFrameData(" << stream_id << ", \"";
299 if (len > 0) {
300 for (size_t i = 0 ; i < len; ++i) {
301 LOG(INFO) << std::hex << (0xFF & static_cast<unsigned int>(data[i]))
302 << std::dec;
305 LOG(INFO) << "\", " << len << ")\n";
308 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
309 EXPECT_EQ(header_stream_id_, stream_id);
310 data_bytes_ += len;
311 LOG(INFO) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
314 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
315 const char* header_data,
316 size_t len) override {
317 ++control_frame_header_data_count_;
318 CHECK_EQ(header_stream_id_, stream_id);
319 if (len == 0) {
320 ++zero_length_control_frame_header_data_count_;
321 // Indicates end-of-header-block.
322 headers_.clear();
323 CHECK(header_buffer_valid_);
324 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
325 header_buffer_.get(), header_buffer_length_, &headers_);
326 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
327 << "Check failed: header_buffer_length_ == parsed_length "
328 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
329 return true;
331 const size_t available = header_buffer_size_ - header_buffer_length_;
332 if (len > available) {
333 header_buffer_valid_ = false;
334 return false;
336 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
337 header_buffer_length_ += len;
338 return true;
341 void OnSynStream(SpdyStreamId stream_id,
342 SpdyStreamId associated_stream_id,
343 SpdyPriority priority,
344 bool fin,
345 bool unidirectional) override {
346 ++syn_frame_count_;
347 if (framer_.protocol_version() > SPDY3) {
348 InitHeaderStreaming(HEADERS, stream_id);
349 } else {
350 InitHeaderStreaming(SYN_STREAM, stream_id);
352 if (fin) {
353 ++fin_flag_count_;
357 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
358 ++syn_reply_frame_count_;
359 if (framer_.protocol_version() > SPDY3) {
360 InitHeaderStreaming(HEADERS, stream_id);
361 } else {
362 InitHeaderStreaming(SYN_REPLY, stream_id);
364 if (fin) {
365 ++fin_flag_count_;
369 void OnRstStream(SpdyStreamId stream_id,
370 SpdyRstStreamStatus status) override {
371 ++fin_frame_count_;
374 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
375 if ((rst_stream_data != NULL) && (len > 0)) {
376 fin_opaque_data_ += string(rst_stream_data, len);
378 return true;
381 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
382 ++setting_count_;
385 void OnSettingsAck() override {
386 DCHECK_LT(SPDY3, framer_.protocol_version());
387 ++settings_ack_received_;
390 void OnSettingsEnd() override {
391 if (framer_.protocol_version() <= SPDY3) { return; }
392 ++settings_ack_sent_;
395 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
397 void OnGoAway(SpdyStreamId last_accepted_stream_id,
398 SpdyGoAwayStatus status) override {
399 ++goaway_count_;
402 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
403 SpdyPriority priority, bool fin, bool end) override {
404 ++headers_frame_count_;
405 InitHeaderStreaming(HEADERS, stream_id);
406 if (fin) {
407 ++fin_flag_count_;
411 void OnWindowUpdate(SpdyStreamId stream_id,
412 uint32 delta_window_size) override {
413 last_window_update_stream_ = stream_id;
414 last_window_update_delta_ = delta_window_size;
417 void OnPushPromise(SpdyStreamId stream_id,
418 SpdyStreamId promised_stream_id,
419 bool end) override {
420 ++push_promise_frame_count_;
421 InitHeaderStreaming(PUSH_PROMISE, stream_id);
422 last_push_promise_stream_ = stream_id;
423 last_push_promise_promised_stream_ = promised_stream_id;
426 void OnContinuation(SpdyStreamId stream_id, bool end) override {
427 ++continuation_count_;
430 void OnAltSvc(SpdyStreamId stream_id,
431 uint32 max_age,
432 uint16 port,
433 StringPiece protocol_id,
434 StringPiece host,
435 StringPiece origin) override {
436 test_altsvc_ir_.set_stream_id(stream_id);
437 test_altsvc_ir_.set_max_age(max_age);
438 test_altsvc_ir_.set_port(port);
439 test_altsvc_ir_.set_protocol_id(protocol_id.as_string());
440 test_altsvc_ir_.set_host(host.as_string());
441 if (origin.length() > 0) {
442 test_altsvc_ir_.set_origin(origin.as_string());
444 ++altsvc_count_;
447 void OnPriority(SpdyStreamId stream_id,
448 SpdyStreamId parent_stream_id,
449 uint8 weight,
450 bool exclusive) override {
451 ++priority_count_;
454 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
455 DLOG(INFO) << "Unknown frame type " << frame_type;
456 return on_unknown_frame_result_;
459 void OnSendCompressedFrame(SpdyStreamId stream_id,
460 SpdyFrameType type,
461 size_t payload_len,
462 size_t frame_len) override {
463 last_payload_len_ = payload_len;
464 last_frame_len_ = frame_len;
467 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
468 SpdyFrameType type,
469 size_t frame_len) override {
470 last_frame_len_ = frame_len;
473 // Convenience function which runs a framer simulation with particular input.
474 void SimulateInFramer(const unsigned char* input, size_t size) {
475 framer_.set_enable_compression(use_compression_);
476 framer_.set_visitor(this);
477 size_t input_remaining = size;
478 const char* input_ptr = reinterpret_cast<const char*>(input);
479 while (input_remaining > 0 &&
480 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
481 // To make the tests more interesting, we feed random (amd small) chunks
482 // into the framer. This simulates getting strange-sized reads from
483 // the socket.
484 const size_t kMaxReadSize = 32;
485 size_t bytes_read =
486 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
487 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
488 input_remaining -= bytes_processed;
489 input_ptr += bytes_processed;
493 void InitHeaderStreaming(SpdyFrameType header_control_type,
494 SpdyStreamId stream_id) {
495 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
496 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
497 header_control_type))) {
498 DLOG(FATAL) << "Attempted to init header streaming with "
499 << "invalid control frame type: "
500 << header_control_type;
502 memset(header_buffer_.get(), 0, header_buffer_size_);
503 header_buffer_length_ = 0;
504 header_stream_id_ = stream_id;
505 header_control_type_ = header_control_type;
506 header_buffer_valid_ = true;
507 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
510 // Override the default buffer size (16K). Call before using the framer!
511 void set_header_buffer_size(size_t header_buffer_size) {
512 header_buffer_size_ = header_buffer_size;
513 header_buffer_.reset(new char[header_buffer_size]);
516 // Largest control frame that the SPDY implementation sends, including the
517 // size of the header.
518 static size_t sent_control_frame_max_size() {
519 return SpdyFramer::kMaxControlFrameSize;
522 static size_t header_data_chunk_max_size() {
523 return SpdyFramer::kHeaderDataChunkMaxSize;
526 SpdyFramer framer_;
527 bool use_compression_;
529 // Counters from the visitor callbacks.
530 int error_count_;
531 int syn_frame_count_;
532 int syn_reply_frame_count_;
533 int headers_frame_count_;
534 int push_promise_frame_count_;
535 int goaway_count_;
536 int setting_count_;
537 int settings_ack_sent_;
538 int settings_ack_received_;
539 int continuation_count_;
540 int altsvc_count_;
541 int priority_count_;
542 SpdyAltSvcIR test_altsvc_ir_;
543 bool on_unknown_frame_result_;
544 SpdyStreamId last_window_update_stream_;
545 uint32 last_window_update_delta_;
546 SpdyStreamId last_push_promise_stream_;
547 SpdyStreamId last_push_promise_promised_stream_;
548 int data_bytes_;
549 int fin_frame_count_; // The count of RST_STREAM type frames received.
550 string fin_opaque_data_;
551 int fin_flag_count_; // The count of frames with the FIN flag set.
552 int zero_length_data_frame_count_; // The count of zero-length data frames.
553 int control_frame_header_data_count_; // The count of chunks received.
554 // The count of zero-length control frame header data chunks received.
555 int zero_length_control_frame_header_data_count_;
556 int data_frame_count_;
557 size_t last_payload_len_;
558 size_t last_frame_len_;
560 // Header block streaming state:
561 scoped_ptr<char[]> header_buffer_;
562 size_t header_buffer_length_;
563 size_t header_buffer_size_;
564 SpdyStreamId header_stream_id_;
565 SpdyFrameType header_control_type_;
566 bool header_buffer_valid_;
567 SpdyHeaderBlock headers_;
570 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
571 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
572 const SpdyFramer& framer) {
573 SpdyFrameReader reader(frame->data(), frame->size());
574 if (framer.protocol_version() > SPDY3) {
575 reader.Seek(3); // Seek past the frame length.
576 } else {
577 reader.Seek(2); // Seek past the frame length.
579 SpdyFrameType frame_type;
580 if (framer.protocol_version() > SPDY3) {
581 uint8 serialized_type;
582 reader.ReadUInt8(&serialized_type);
583 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
584 serialized_type);
585 DCHECK_EQ(HEADERS, frame_type);
586 uint8 flags;
587 reader.ReadUInt8(&flags);
588 if (flags & HEADERS_FLAG_PRIORITY) {
589 frame_type = SYN_STREAM;
591 } else {
592 uint16 serialized_type;
593 reader.ReadUInt16(&serialized_type);
594 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
595 serialized_type);
596 DCHECK(frame_type == HEADERS ||
597 frame_type == SYN_STREAM) << frame_type;
600 if (frame_type == SYN_STREAM) {
601 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
602 frame->size() - framer.GetSynStreamMinimumSize());
603 } else {
604 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
605 frame->size() - framer.GetHeadersMinimumSize());
609 } // namespace test
611 } // namespace net
613 using net::test::SetFrameLength;
614 using net::test::SetFrameFlags;
615 using net::test::CompareCharArraysWithHexError;
616 using net::test::SpdyFramerTestUtil;
617 using net::test::TestSpdyVisitor;
618 using net::test::GetSerializedHeaders;
620 namespace net {
622 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
623 protected:
624 void SetUp() override {
625 spdy_version_ = GetParam();
626 spdy_version_ch_ = static_cast<unsigned char>(
627 SpdyConstants::SerializeMajorVersion(spdy_version_));
630 void CompareFrame(const string& description,
631 const SpdyFrame& actual_frame,
632 const unsigned char* expected,
633 const int expected_len) {
634 const unsigned char* actual =
635 reinterpret_cast<const unsigned char*>(actual_frame.data());
636 CompareCharArraysWithHexError(
637 description, actual, actual_frame.size(), expected, expected_len);
640 void CompareFrames(const string& description,
641 const SpdyFrame& expected_frame,
642 const SpdyFrame& actual_frame) {
643 CompareCharArraysWithHexError(
644 description,
645 reinterpret_cast<const unsigned char*>(expected_frame.data()),
646 expected_frame.size(),
647 reinterpret_cast<const unsigned char*>(actual_frame.data()),
648 actual_frame.size());
651 // Returns true if the two header blocks have equivalent content.
652 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
653 const SpdyHeaderBlock* actual) {
654 if (expected->size() != actual->size()) {
655 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
656 << actual->size() << ".";
657 return false;
659 for (SpdyHeaderBlock::const_iterator it = expected->begin();
660 it != expected->end();
661 ++it) {
662 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
663 if (it2 == actual->end()) {
664 LOG(ERROR) << "Expected header name '" << it->first << "'.";
665 return false;
667 if (it->second.compare(it2->second) != 0) {
668 LOG(ERROR) << "Expected header named '" << it->first
669 << "' to have a value of '" << it->second
670 << "'. The actual value received was '" << it2->second
671 << "'.";
672 return false;
675 return true;
678 bool IsSpdy2() { return spdy_version_ == SPDY2; }
679 bool IsSpdy3() { return spdy_version_ == SPDY3; }
680 bool IsSpdy4() { return spdy_version_ == SPDY4; }
682 // Version of SPDY protocol to be used.
683 SpdyMajorVersion spdy_version_;
684 unsigned char spdy_version_ch_;
687 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
688 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
689 SpdyFramerTest,
690 ::testing::Values(SPDY2, SPDY3, SPDY4));
692 // Test that we ignore cookie where both name and value are empty.
693 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
694 if (spdy_version_ > SPDY3) {
695 // Not implemented for hpack.
696 return;
699 SpdyFramer framer(spdy_version_);
700 framer.set_enable_compression(true);
701 SpdyHeadersIR headers(1);
702 headers.set_priority(1);
703 headers.SetHeader("cookie",
704 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
705 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
706 EXPECT_TRUE(frame.get() != NULL);
708 TestSpdyVisitor visitor(spdy_version_);
709 visitor.use_compression_ = true;
710 visitor.SimulateInFramer(
711 reinterpret_cast<unsigned char*>(frame->data()),
712 frame->size());
714 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
715 EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
716 &visitor.headers_));
717 EXPECT_EQ(1u, visitor.headers_.size());
718 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
721 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
722 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
723 SpdyFramer framer(spdy_version_);
724 framer.set_enable_compression(false);
726 // Encode the header block into a Headers frame.
727 SpdyHeadersIR headers(1);
728 headers.set_priority(1);
729 headers.SetHeader("alpha", "beta");
730 headers.SetHeader("gamma", "charlie");
731 headers.SetHeader("cookie", "key1=value1; key2=value2");
732 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
733 EXPECT_TRUE(frame.get() != NULL);
735 TestSpdyVisitor visitor(spdy_version_);
736 visitor.use_compression_ = false;
737 visitor.SimulateInFramer(
738 reinterpret_cast<unsigned char*>(frame->data()),
739 frame->size());
741 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
742 EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
743 &visitor.headers_));
746 // Test that if there's not a full frame, we fail to parse it.
747 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
748 SpdyFramer framer(spdy_version_);
749 framer.set_enable_compression(false);
751 // Encode the header block into a Headers frame.
752 SpdyHeadersIR headers(1);
753 headers.set_priority(1);
754 headers.SetHeader("alpha", "beta");
755 headers.SetHeader("gamma", "charlie");
756 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
757 EXPECT_TRUE(frame.get() != NULL);
759 TestSpdyVisitor visitor(spdy_version_);
760 visitor.use_compression_ = false;
761 visitor.SimulateInFramer(
762 reinterpret_cast<unsigned char*>(frame->data()),
763 frame->size() - 2);
765 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
766 EXPECT_EQ(0u, visitor.headers_.size());
769 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
770 // (but don't crash).
771 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
772 if (spdy_version_ > SPDY3) {
773 return;
775 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
776 SpdyFramer framer(spdy_version_);
777 framer.set_visitor(&visitor);
779 SpdySynReplyIR syn_reply(0);
780 syn_reply.SetHeader("alpha", "beta");
781 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
782 ASSERT_TRUE(frame.get() != NULL);
784 // We shouldn't have to read the whole frame before we signal an error.
785 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
786 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
787 EXPECT_TRUE(framer.HasError());
788 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
789 << SpdyFramer::ErrorCodeToString(framer.error_code());
792 // Test that if we receive a HEADERS with stream ID zero, we signal an error
793 // (but don't crash).
794 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
795 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
796 SpdyFramer framer(spdy_version_);
797 framer.set_visitor(&visitor);
799 SpdyHeadersIR headers_ir(0);
800 headers_ir.SetHeader("alpha", "beta");
801 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
802 ASSERT_TRUE(frame.get() != NULL);
804 // We shouldn't have to read the whole frame before we signal an error.
805 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
806 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
807 EXPECT_TRUE(framer.HasError());
808 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
809 << SpdyFramer::ErrorCodeToString(framer.error_code());
812 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
813 // error (but don't crash).
814 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
815 if (spdy_version_ <= SPDY3) {
816 return;
819 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
820 SpdyFramer framer(spdy_version_);
821 framer.set_visitor(&visitor);
823 SpdyPushPromiseIR push_promise(0, 4);
824 push_promise.SetHeader("alpha", "beta");
825 scoped_ptr<SpdySerializedFrame> frame(
826 framer.SerializePushPromise(push_promise));
827 ASSERT_TRUE(frame.get() != NULL);
829 // We shouldn't have to read the whole frame before we signal an error.
830 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
831 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
832 EXPECT_TRUE(framer.HasError());
833 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
834 << SpdyFramer::ErrorCodeToString(framer.error_code());
837 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
838 // signal an error (but don't crash).
839 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
840 if (spdy_version_ <= SPDY3) {
841 return;
844 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
845 SpdyFramer framer(spdy_version_);
846 framer.set_visitor(&visitor);
848 SpdyPushPromiseIR push_promise(3, 0);
849 push_promise.SetHeader("alpha", "beta");
850 scoped_ptr<SpdySerializedFrame> frame(
851 framer.SerializePushPromise(push_promise));
852 ASSERT_TRUE(frame.get() != NULL);
854 // We shouldn't have to read the whole frame before we signal an error.
855 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
856 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
857 EXPECT_TRUE(framer.HasError());
858 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
859 << SpdyFramer::ErrorCodeToString(framer.error_code());
862 TEST_P(SpdyFramerTest, DuplicateHeader) {
863 if (spdy_version_ > SPDY3) {
864 // TODO(jgraettinger): Punting on this because we haven't determined
865 // whether duplicate HPACK headers other than Cookie are an error.
866 // If they are, this will need to be updated to use HpackOutputStream.
867 return;
869 SpdyFramer framer(spdy_version_);
870 // Frame builder with plentiful buffer size.
871 SpdyFrameBuilder frame(1024, spdy_version_);
872 if (spdy_version_ <= SPDY3) {
873 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
874 frame.WriteUInt32(3); // stream_id
875 frame.WriteUInt32(0); // associated stream id
876 frame.WriteUInt16(0); // Priority.
877 } else {
878 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
879 frame.WriteUInt32(framer.GetHighestPriority());
882 if (IsSpdy2()) {
883 frame.WriteUInt16(2); // Number of headers.
884 frame.WriteStringPiece16("name");
885 frame.WriteStringPiece16("value1");
886 frame.WriteStringPiece16("name");
887 frame.WriteStringPiece16("value2");
888 } else {
889 frame.WriteUInt32(2); // Number of headers.
890 frame.WriteStringPiece32("name");
891 frame.WriteStringPiece32("value1");
892 frame.WriteStringPiece32("name");
893 frame.WriteStringPiece32("value2");
895 // write the length
896 frame.RewriteLength(framer);
898 SpdyHeaderBlock new_headers;
899 framer.set_enable_compression(false);
900 scoped_ptr<SpdyFrame> control_frame(frame.take());
901 base::StringPiece serialized_headers =
902 GetSerializedHeaders(control_frame.get(), framer);
903 // This should fail because duplicate headers are verboten by the spec.
904 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
905 serialized_headers.size(),
906 &new_headers));
909 TEST_P(SpdyFramerTest, MultiValueHeader) {
910 SpdyFramer framer(spdy_version_);
911 // Frame builder with plentiful buffer size.
912 SpdyFrameBuilder frame(1024, spdy_version_);
913 if (spdy_version_ <= SPDY3) {
914 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
915 frame.WriteUInt32(3); // stream_id
916 frame.WriteUInt32(0); // associated stream id
917 frame.WriteUInt16(0); // Priority.
918 } else {
919 frame.BeginNewFrame(framer,
920 HEADERS,
921 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
923 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
924 frame.WriteUInt8(255); // Priority weight.
927 string value("value1\0value2", 13);
928 if (IsSpdy2()) {
929 frame.WriteUInt16(1); // Number of headers.
930 frame.WriteStringPiece16("name");
931 frame.WriteStringPiece16(value);
932 } else if (spdy_version_ > SPDY3) {
933 // TODO(jgraettinger): If this pattern appears again, move to test class.
934 std::map<string, string> header_set;
935 header_set["name"] = value;
936 string buffer;
937 HpackEncoder encoder(ObtainHpackHuffmanTable());
938 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
939 frame.WriteBytes(&buffer[0], buffer.size());
940 } else {
941 frame.WriteUInt32(1); // Number of headers.
942 frame.WriteStringPiece32("name");
943 frame.WriteStringPiece32(value);
945 // write the length
946 frame.RewriteLength(framer);
948 framer.set_enable_compression(false);
949 scoped_ptr<SpdyFrame> control_frame(frame.take());
951 TestSpdyVisitor visitor(spdy_version_);
952 visitor.use_compression_ = false;
953 visitor.SimulateInFramer(
954 reinterpret_cast<unsigned char*>(control_frame->data()),
955 control_frame->size());
957 EXPECT_THAT(visitor.headers_,
958 testing::ElementsAre(testing::Pair("name", value)));
961 TEST_P(SpdyFramerTest, BasicCompression) {
962 if (spdy_version_ > SPDY3) {
963 // Deflate compression doesn't apply to HPACK.
964 return;
966 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
967 SpdyFramer framer(spdy_version_);
968 framer.set_debug_visitor(visitor.get());
969 SpdySynStreamIR syn_stream(1);
970 syn_stream.set_priority(1);
971 syn_stream.SetHeader("server", "SpdyServer 1.0");
972 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
973 syn_stream.SetHeader("status", "200");
974 syn_stream.SetHeader("version", "HTTP/1.1");
975 syn_stream.SetHeader("content-type", "text/html");
976 syn_stream.SetHeader("content-length", "12");
977 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
978 size_t uncompressed_size1 = visitor->last_payload_len_;
979 size_t compressed_size1 =
980 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
981 if (IsSpdy2()) {
982 EXPECT_EQ(139u, uncompressed_size1);
983 #if defined(USE_SYSTEM_ZLIB)
984 EXPECT_EQ(155u, compressed_size1);
985 #else // !defined(USE_SYSTEM_ZLIB)
986 EXPECT_EQ(135u, compressed_size1);
987 #endif // !defined(USE_SYSTEM_ZLIB)
988 } else {
989 EXPECT_EQ(165u, uncompressed_size1);
990 #if defined(USE_SYSTEM_ZLIB)
991 EXPECT_EQ(181u, compressed_size1);
992 #else // !defined(USE_SYSTEM_ZLIB)
993 EXPECT_EQ(117u, compressed_size1);
994 #endif // !defined(USE_SYSTEM_ZLIB)
996 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
997 size_t uncompressed_size2 = visitor->last_payload_len_;
998 size_t compressed_size2 =
999 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1001 // Expect the second frame to be more compact than the first.
1002 EXPECT_LE(frame2->size(), frame1->size());
1004 // Decompress the first frame
1005 scoped_ptr<SpdyFrame> frame3(
1006 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
1008 // Decompress the second frame
1009 visitor.reset(new TestSpdyVisitor(spdy_version_));
1010 framer.set_debug_visitor(visitor.get());
1011 scoped_ptr<SpdyFrame> frame4(
1012 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1013 size_t uncompressed_size4 =
1014 frame4->size() - framer.GetSynStreamMinimumSize();
1015 size_t compressed_size4 =
1016 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1017 if (IsSpdy2()) {
1018 EXPECT_EQ(139u, uncompressed_size4);
1019 #if defined(USE_SYSTEM_ZLIB)
1020 EXPECT_EQ(149u, compressed_size4);
1021 #else // !defined(USE_SYSTEM_ZLIB)
1022 EXPECT_EQ(101u, compressed_size4);
1023 #endif // !defined(USE_SYSTEM_ZLIB)
1024 } else {
1025 EXPECT_EQ(165u, uncompressed_size4);
1026 #if defined(USE_SYSTEM_ZLIB)
1027 EXPECT_EQ(175u, compressed_size4);
1028 #else // !defined(USE_SYSTEM_ZLIB)
1029 EXPECT_EQ(102u, compressed_size4);
1030 #endif // !defined(USE_SYSTEM_ZLIB)
1033 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1034 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1035 EXPECT_EQ(compressed_size2, compressed_size4);
1037 // Expect frames 3 & 4 to be the same.
1038 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1040 // Expect frames 3 to be the same as a uncompressed frame created
1041 // from scratch.
1042 framer.set_enable_compression(false);
1043 scoped_ptr<SpdyFrame> uncompressed_frame(
1044 framer.SerializeSynStream(syn_stream));
1045 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1048 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1049 // See crbug.com/172383
1050 SpdyHeadersIR headers(1);
1051 headers.SetHeader("server", "SpdyServer 1.0");
1052 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1053 headers.SetHeader("status", "200");
1054 headers.SetHeader("version", "HTTP/1.1");
1055 headers.SetHeader("content-type", "text/html");
1056 headers.SetHeader("content-length", "12");
1057 headers.SetHeader("x-empty-header", "");
1059 SpdyFramer framer(spdy_version_);
1060 framer.set_enable_compression(true);
1061 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1064 TEST_P(SpdyFramerTest, Basic) {
1065 const unsigned char kV2Input[] = {
1066 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1067 0x00, 0x00, 0x00, 0x14,
1068 0x00, 0x00, 0x00, 0x01,
1069 0x00, 0x00, 0x00, 0x00,
1070 0x00, 0x00, 0x00, 0x01,
1071 0x00, 0x02, 'h', 'h',
1072 0x00, 0x02, 'v', 'v',
1074 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1075 0x00, 0x00, 0x00, 0x18,
1076 0x00, 0x00, 0x00, 0x01,
1077 0x00, 0x00, 0x00, 0x02,
1078 0x00, 0x02, 'h', '2',
1079 0x00, 0x02, 'v', '2',
1080 0x00, 0x02, 'h', '3',
1081 0x00, 0x02, 'v', '3',
1083 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1084 0x00, 0x00, 0x00, 0x0c,
1085 0xde, 0xad, 0xbe, 0xef,
1086 0xde, 0xad, 0xbe, 0xef,
1087 0xde, 0xad, 0xbe, 0xef,
1089 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1090 0x00, 0x00, 0x00, 0x0c,
1091 0x00, 0x00, 0x00, 0x03,
1092 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00,
1095 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1096 0x00, 0x00, 0x00, 0x08,
1097 0xde, 0xad, 0xbe, 0xef,
1098 0xde, 0xad, 0xbe, 0xef,
1100 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1101 0x00, 0x00, 0x00, 0x04,
1102 0xde, 0xad, 0xbe, 0xef,
1104 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1105 0x00, 0x00, 0x00, 0x08,
1106 0x00, 0x00, 0x00, 0x01,
1107 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1109 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1110 0x00, 0x00, 0x00, 0x00,
1112 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1113 0x00, 0x00, 0x00, 0x08,
1114 0x00, 0x00, 0x00, 0x03,
1115 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1118 const unsigned char kV3Input[] = {
1119 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1120 0x00, 0x00, 0x00, 0x1a,
1121 0x00, 0x00, 0x00, 0x01,
1122 0x00, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00,
1124 0x00, 0x01, 0x00, 0x00,
1125 0x00, 0x02, 'h', 'h',
1126 0x00, 0x00, 0x00, 0x02,
1127 'v', 'v',
1129 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1130 0x00, 0x00, 0x00, 0x20,
1131 0x00, 0x00, 0x00, 0x01,
1132 0x00, 0x00, 0x00, 0x02,
1133 0x00, 0x00, 0x00, 0x02,
1134 'h', '2',
1135 0x00, 0x00, 0x00, 0x02,
1136 'v', '2', 0x00, 0x00,
1137 0x00, 0x02, 'h', '3',
1138 0x00, 0x00, 0x00, 0x02,
1139 'v', '3',
1141 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1142 0x00, 0x00, 0x00, 0x0c,
1143 0xde, 0xad, 0xbe, 0xef,
1144 0xde, 0xad, 0xbe, 0xef,
1145 0xde, 0xad, 0xbe, 0xef,
1147 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1148 0x00, 0x00, 0x00, 0x0e,
1149 0x00, 0x00, 0x00, 0x03,
1150 0x00, 0x00, 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x00,
1152 0x00, 0x00,
1154 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1155 0x00, 0x00, 0x00, 0x08,
1156 0xde, 0xad, 0xbe, 0xef,
1157 0xde, 0xad, 0xbe, 0xef,
1159 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1160 0x00, 0x00, 0x00, 0x04,
1161 0xde, 0xad, 0xbe, 0xef,
1163 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1164 0x00, 0x00, 0x00, 0x08,
1165 0x00, 0x00, 0x00, 0x01,
1166 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1168 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1169 0x00, 0x00, 0x00, 0x00,
1171 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1172 0x00, 0x00, 0x00, 0x08,
1173 0x00, 0x00, 0x00, 0x03,
1174 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1177 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1178 // HEADERS frames with PRIORITY and END_HEADERS set.
1179 const unsigned char kV4Input[] = {
1180 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1181 0x24, 0x00, 0x00, 0x00,
1182 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1183 0x00, 0x82, // :method: GET
1185 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1186 0x04, 0x00, 0x00, 0x00, // Stream 1
1187 0x01, 0x8c, // :status: 200
1189 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1190 0x00, 0x00, 0x00, 0x00,
1191 0x01, 0xde, 0xad, 0xbe,
1192 0xef, 0xde, 0xad, 0xbe,
1193 0xef, 0xde, 0xad, 0xbe,
1194 0xef,
1196 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1197 0x24, 0x00, 0x00, 0x00,
1198 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1199 0x00, 0x82, // :method: GET
1201 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1202 0x00, 0x00, 0x00, 0x00,
1203 0x03, 0xde, 0xad, 0xbe,
1204 0xef, 0xde, 0xad, 0xbe,
1205 0xef,
1207 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1208 0x00, 0x00, 0x00, 0x00,
1209 0x01, 0xde, 0xad, 0xbe,
1210 0xef,
1212 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1213 0x00, 0x00, 0x00, 0x00,
1214 0x01, 0x00, 0x00, 0x00,
1215 0x08, // RST_STREAM_CANCEL
1217 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1218 0x00, 0x00, 0x00, 0x00,
1219 0x03,
1221 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1222 0x00, 0x00, 0x00, 0x00,
1223 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1224 0x08, 0x52, 0x45, 0x53, // opaque data
1225 0x45, 0x54, 0x53, 0x54,
1226 0x52, 0x45, 0x41, 0x4d,
1229 TestSpdyVisitor visitor(spdy_version_);
1230 if (IsSpdy2()) {
1231 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1232 } else if (IsSpdy3()) {
1233 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1234 } else {
1235 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1238 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1239 EXPECT_EQ(24, visitor.data_bytes_);
1240 EXPECT_EQ(0, visitor.error_count_);
1241 EXPECT_EQ(2, visitor.fin_frame_count_);
1243 if (IsSpdy4()) {
1244 EXPECT_EQ(3, visitor.headers_frame_count_);
1245 EXPECT_EQ(0, visitor.syn_frame_count_);
1246 base::StringPiece reset_stream = "RESETSTREAM";
1247 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1248 } else {
1249 EXPECT_EQ(1, visitor.headers_frame_count_);
1250 EXPECT_EQ(2, visitor.syn_frame_count_);
1251 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1254 EXPECT_EQ(0, visitor.fin_flag_count_);
1255 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1256 EXPECT_EQ(4, visitor.data_frame_count_);
1257 visitor.fin_opaque_data_.clear();
1260 // Test that the FIN flag on a data frame signifies EOF.
1261 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1262 const unsigned char kV2Input[] = {
1263 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1264 0x00, 0x00, 0x00, 0x14,
1265 0x00, 0x00, 0x00, 0x01,
1266 0x00, 0x00, 0x00, 0x00,
1267 0x00, 0x00, 0x00, 0x01,
1268 0x00, 0x02, 'h', 'h',
1269 0x00, 0x02, 'v', 'v',
1271 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1272 0x00, 0x00, 0x00, 0x10,
1273 0x00, 0x00, 0x00, 0x01,
1274 0x00, 0x00, 0x00, 0x01,
1275 0x00, 0x02, 'a', 'a',
1276 0x00, 0x02, 'b', 'b',
1278 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1279 0x00, 0x00, 0x00, 0x0c,
1280 0xde, 0xad, 0xbe, 0xef,
1281 0xde, 0xad, 0xbe, 0xef,
1282 0xde, 0xad, 0xbe, 0xef,
1284 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1285 0x01, 0x00, 0x00, 0x04,
1286 0xde, 0xad, 0xbe, 0xef,
1288 const unsigned char kV3Input[] = {
1289 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1290 0x00, 0x00, 0x00, 0x1a,
1291 0x00, 0x00, 0x00, 0x01,
1292 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x01, 0x00, 0x00,
1295 0x00, 0x02, 'h', 'h',
1296 0x00, 0x00, 0x00, 0x02,
1297 'v', 'v',
1299 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1300 0x00, 0x00, 0x00, 0x14,
1301 0x00, 0x00, 0x00, 0x01,
1302 0x00, 0x00, 0x00, 0x01,
1303 0x00, 0x00, 0x00, 0x02,
1304 'a', 'a', 0x00, 0x00,
1305 0x00, 0x02, 'b', 'b',
1307 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1308 0x00, 0x00, 0x00, 0x0c,
1309 0xde, 0xad, 0xbe, 0xef,
1310 0xde, 0xad, 0xbe, 0xef,
1311 0xde, 0xad, 0xbe, 0xef,
1313 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1314 0x01, 0x00, 0x00, 0x04,
1315 0xde, 0xad, 0xbe, 0xef,
1318 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1319 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1320 const unsigned char kV4Input[] = {
1321 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1322 0x24, 0x00, 0x00, 0x00, // Stream 1
1323 0x01, 0x00, 0x00, 0x00, // Priority 0
1324 0x00, 0x82, // :method: GET
1326 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1327 0x04, 0x00, 0x00, 0x00, // Stream 1
1328 0x01, 0x8c, // :status: 200
1330 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1331 0x00, 0x00, 0x00, 0x00,
1332 0x01, 0xde, 0xad, 0xbe,
1333 0xef, 0xde, 0xad, 0xbe,
1334 0xef, 0xde, 0xad, 0xbe,
1335 0xef,
1337 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1338 0x01, 0x00, 0x00, 0x00,
1339 0x01, 0xde, 0xad, 0xbe,
1340 0xef,
1343 TestSpdyVisitor visitor(spdy_version_);
1344 if (IsSpdy2()) {
1345 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1346 } else if (IsSpdy3()) {
1347 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1348 } else {
1349 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1352 EXPECT_EQ(0, visitor.error_count_);
1353 if (IsSpdy4()) {
1354 EXPECT_EQ(0, visitor.syn_frame_count_);
1355 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1356 EXPECT_EQ(2, visitor.headers_frame_count_);
1357 } else {
1358 EXPECT_EQ(1, visitor.syn_frame_count_);
1359 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1360 EXPECT_EQ(0, visitor.headers_frame_count_);
1362 EXPECT_EQ(16, visitor.data_bytes_);
1363 EXPECT_EQ(0, visitor.fin_frame_count_);
1364 EXPECT_EQ(0, visitor.fin_flag_count_);
1365 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1366 EXPECT_EQ(2, visitor.data_frame_count_);
1369 // Test that the FIN flag on a SYN reply frame signifies EOF.
1370 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1371 const unsigned char kV2Input[] = {
1372 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1373 0x01, 0x00, 0x00, 0x00,
1374 0x14, 0x00, 0x00, 0x00,
1375 0x01, 0x00, 0x00, 0x00,
1376 0x00, 0x00, 0x00, 0x00,
1377 0x01, 0x00, 0x02, 'h',
1378 'h', 0x00, 0x02, 'v',
1379 'v',
1381 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1382 0x02, 0x01, 0x00, 0x00,
1383 0x10, 0x00, 0x00, 0x00,
1384 0x01, 0x00, 0x00, 0x00,
1385 0x01, 0x00, 0x02, 'a',
1386 'a', 0x00, 0x02, 'b',
1387 'b',
1389 const unsigned char kV3Input[] = {
1390 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1391 0x01, 0x00, 0x00, 0x00,
1392 0x1a, 0x00, 0x00, 0x00,
1393 0x01, 0x00, 0x00, 0x00,
1394 0x00, 0x00, 0x00, 0x00,
1395 0x00, 0x00, 0x01, 0x00,
1396 0x00, 0x00, 0x02, 'h',
1397 'h', 0x00, 0x00, 0x00,
1398 0x02, 'v', 'v',
1400 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1401 0x02, 0x01, 0x00, 0x00,
1402 0x14, 0x00, 0x00, 0x00,
1403 0x01, 0x00, 0x00, 0x00,
1404 0x01, 0x00, 0x00, 0x00,
1405 0x02, 'a', 'a', 0x00,
1406 0x00, 0x00, 0x02, 'b',
1407 'b',
1410 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1411 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1412 const unsigned char kV4Input[] = {
1413 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1414 0x24, 0x00, 0x00, 0x00,
1415 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1416 0x00, 0x82, // :method: GET
1418 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1419 0x05, 0x00, 0x00, 0x00,
1420 0x01, 0x8c, // Stream 1, :status: 200
1423 TestSpdyVisitor visitor(spdy_version_);
1424 if (IsSpdy2()) {
1425 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1426 } else if (IsSpdy3()) {
1427 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1428 } else {
1429 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1432 EXPECT_EQ(0, visitor.error_count_);
1433 if (IsSpdy4()) {
1434 EXPECT_EQ(0, visitor.syn_frame_count_);
1435 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1436 EXPECT_EQ(2, visitor.headers_frame_count_);
1437 } else {
1438 EXPECT_EQ(1, visitor.syn_frame_count_);
1439 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1440 EXPECT_EQ(0, visitor.headers_frame_count_);
1442 EXPECT_EQ(0, visitor.data_bytes_);
1443 EXPECT_EQ(0, visitor.fin_frame_count_);
1444 EXPECT_EQ(1, visitor.fin_flag_count_);
1445 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1446 EXPECT_EQ(0, visitor.data_frame_count_);
1449 TEST_P(SpdyFramerTest, HeaderCompression) {
1450 if (spdy_version_ > SPDY3) {
1451 // Deflate compression doesn't apply to HPACK.
1452 return;
1454 SpdyFramer send_framer(spdy_version_);
1455 SpdyFramer recv_framer(spdy_version_);
1457 send_framer.set_enable_compression(true);
1458 recv_framer.set_enable_compression(true);
1460 const char kHeader1[] = "header1";
1461 const char kHeader2[] = "header2";
1462 const char kHeader3[] = "header3";
1463 const char kValue1[] = "value1";
1464 const char kValue2[] = "value2";
1465 const char kValue3[] = "value3";
1467 // SYN_STREAM #1
1468 SpdyHeaderBlock block;
1469 block[kHeader1] = kValue1;
1470 block[kHeader2] = kValue2;
1471 SpdySynStreamIR syn_ir_1(1);
1472 syn_ir_1.set_name_value_block(block);
1473 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1474 EXPECT_TRUE(syn_frame_1.get() != NULL);
1476 // SYN_STREAM #2
1477 block[kHeader3] = kValue3;
1478 SpdySynStreamIR syn_stream(3);
1479 syn_stream.set_name_value_block(block);
1480 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1481 EXPECT_TRUE(syn_frame_2.get() != NULL);
1483 // Now start decompressing
1484 scoped_ptr<SpdyFrame> decompressed;
1485 scoped_ptr<SpdyFrame> uncompressed;
1486 base::StringPiece serialized_headers;
1487 SpdyHeaderBlock decompressed_headers;
1489 // Decompress SYN_STREAM #1
1490 decompressed.reset(
1491 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1492 EXPECT_TRUE(decompressed.get() != NULL);
1493 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1494 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1495 serialized_headers.size(),
1496 &decompressed_headers));
1497 EXPECT_EQ(2u, decompressed_headers.size());
1498 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1499 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1501 // Decompress SYN_STREAM #2
1502 decompressed.reset(
1503 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1504 EXPECT_TRUE(decompressed.get() != NULL);
1505 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1506 decompressed_headers.clear();
1507 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1508 serialized_headers.size(),
1509 &decompressed_headers));
1510 EXPECT_EQ(3u, decompressed_headers.size());
1511 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1512 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1513 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1516 // Verify we can decompress the stream even if handed over to the
1517 // framer 1 byte at a time.
1518 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1519 SpdyFramer send_framer(spdy_version_);
1521 send_framer.set_enable_compression(true);
1523 const char kHeader1[] = "header1";
1524 const char kHeader2[] = "header2";
1525 const char kValue1[] = "value1";
1526 const char kValue2[] = "value2";
1528 SpdyHeadersIR headers(1);
1529 headers.SetHeader(kHeader1, kValue1);
1530 headers.SetHeader(kHeader2, kValue2);
1531 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1532 EXPECT_TRUE(headers_frame.get() != NULL);
1534 const char bytes[] = "this is a test test test test test!";
1535 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1536 data_ir.set_fin(true);
1537 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1538 EXPECT_TRUE(send_frame.get() != NULL);
1540 // Run the inputs through the framer.
1541 TestSpdyVisitor visitor(spdy_version_);
1542 visitor.use_compression_ = true;
1543 const unsigned char* data;
1544 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1545 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1546 visitor.SimulateInFramer(data + idx, 1);
1547 ASSERT_EQ(0, visitor.error_count_);
1549 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1550 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1551 visitor.SimulateInFramer(data + idx, 1);
1552 ASSERT_EQ(0, visitor.error_count_);
1555 EXPECT_EQ(0, visitor.error_count_);
1556 EXPECT_EQ(0, visitor.syn_frame_count_);
1557 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1558 EXPECT_EQ(1, visitor.headers_frame_count_);
1559 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1560 EXPECT_EQ(0, visitor.fin_frame_count_);
1561 EXPECT_EQ(0, visitor.fin_flag_count_);
1562 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1563 EXPECT_EQ(1, visitor.data_frame_count_);
1566 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1567 SpdyFramer framer(spdy_version_);
1568 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1569 SpdyWindowUpdateIR(1, 0x12345678)));
1571 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1572 const unsigned char kV3FrameData[] = { // Also applies for V2.
1573 0x80, spdy_version_ch_, 0x00, 0x09,
1574 0x00, 0x00, 0x00, 0x08,
1575 0x00, 0x00, 0x00, 0x01,
1576 0x12, 0x34, 0x56, 0x78
1578 const unsigned char kV4FrameData[] = {
1579 0x00, 0x00, 0x04, 0x08,
1580 0x00, 0x00, 0x00, 0x00,
1581 0x01, 0x12, 0x34, 0x56,
1582 0x78
1585 if (IsSpdy4()) {
1586 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1587 } else {
1588 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1592 TEST_P(SpdyFramerTest, CreateDataFrame) {
1593 SpdyFramer framer(spdy_version_);
1596 const char kDescription[] = "'hello' data frame, no FIN";
1597 const unsigned char kV3FrameData[] = { // Also applies for V2.
1598 0x00, 0x00, 0x00, 0x01,
1599 0x00, 0x00, 0x00, 0x05,
1600 'h', 'e', 'l', 'l',
1603 const unsigned char kV4FrameData[] = {
1604 0x00, 0x00, 0x05, 0x00,
1605 0x00, 0x00, 0x00, 0x00,
1606 0x01, 'h', 'e', 'l',
1607 'l', 'o'
1609 const char bytes[] = "hello";
1611 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1612 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1613 if (IsSpdy4()) {
1614 CompareFrame(
1615 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1616 } else {
1617 CompareFrame(
1618 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1621 SpdyDataIR data_header_ir(1);
1622 data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
1623 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1624 data_header_ir));
1625 CompareCharArraysWithHexError(
1626 kDescription,
1627 reinterpret_cast<const unsigned char*>(frame->data()),
1628 framer.GetDataFrameMinimumSize(),
1629 IsSpdy4() ? kV4FrameData : kV3FrameData,
1630 framer.GetDataFrameMinimumSize());
1634 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1635 const unsigned char kV3FrameData[] = { // Also applies for V2.
1636 0x00, 0x00, 0x00, 0x01,
1637 0x00, 0x00, 0x00, 0x05,
1638 'h', 'e', 'l', 'l',
1642 const unsigned char kV4FrameData[] = {
1643 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1644 0x08, 0x00, 0x00, 0x00,
1645 0x01, 0xf7, // Pad length field.
1646 'h', 'e', 'l', 'l', // Data
1647 'o',
1648 // Padding of 247 0x00(s).
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1671 const char bytes[] = "hello";
1673 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1674 // 247 zeros and the pad length field make the overall padding to be 248
1675 // bytes.
1676 data_ir.set_padding_len(248);
1677 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1678 if (IsSpdy4()) {
1679 CompareFrame(
1680 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1681 } else {
1682 CompareFrame(
1683 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1686 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1687 CompareCharArraysWithHexError(
1688 kDescription,
1689 reinterpret_cast<const unsigned char*>(frame->data()),
1690 framer.GetDataFrameMinimumSize(),
1691 IsSpdy4() ? kV4FrameData : kV3FrameData,
1692 framer.GetDataFrameMinimumSize());
1696 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1697 const unsigned char kV3FrameData[] = { // Also applies for V2.
1698 0x00, 0x00, 0x00, 0x01,
1699 0x00, 0x00, 0x00, 0x05,
1700 'h', 'e', 'l', 'l',
1704 const unsigned char kV4FrameData[] = {
1705 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1706 0x08, 0x00, 0x00, 0x00,
1707 0x01, 0x07, // Pad length field.
1708 'h', 'e', 'l', 'l', // Data
1709 'o',
1710 0x00, 0x00, 0x00, 0x00, // Padding
1711 0x00, 0x00, 0x00
1713 const char bytes[] = "hello";
1715 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1716 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1717 data_ir.set_padding_len(8);
1718 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1719 if (IsSpdy4()) {
1720 CompareFrame(
1721 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1722 } else {
1723 CompareFrame(
1724 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1729 const char kDescription[] =
1730 "'hello' data frame with 1 byte padding, no FIN";
1731 const unsigned char kV3FrameData[] = { // Also applies for V2.
1732 0x00, 0x00, 0x00, 0x01,
1733 0x00, 0x00, 0x00, 0x05,
1734 'h', 'e', 'l', 'l',
1738 const unsigned char kV4FrameData[] = {
1739 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1740 0x08, 0x00, 0x00, 0x00,
1741 0x01, 0x00, // Pad length field.
1742 'h', 'e', 'l', 'l', // Data
1743 'o',
1745 const char bytes[] = "hello";
1747 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1748 // The pad length field itself is used for the 1-byte padding and no padding
1749 // payload is needed.
1750 data_ir.set_padding_len(1);
1751 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1752 if (IsSpdy4()) {
1753 CompareFrame(
1754 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1755 } else {
1756 CompareFrame(
1757 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1760 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1761 CompareCharArraysWithHexError(
1762 kDescription,
1763 reinterpret_cast<const unsigned char*>(frame->data()),
1764 framer.GetDataFrameMinimumSize(),
1765 IsSpdy4() ? kV4FrameData : kV3FrameData,
1766 framer.GetDataFrameMinimumSize());
1770 const char kDescription[] = "Data frame with negative data byte, no FIN";
1771 const unsigned char kV3FrameData[] = { // Also applies for V2.
1772 0x00, 0x00, 0x00, 0x01,
1773 0x00, 0x00, 0x00, 0x01,
1774 0xff
1776 const unsigned char kV4FrameData[] = {
1777 0x00, 0x00, 0x01, 0x00, 0x00,
1778 0x00, 0x00, 0x00, 0x01,
1779 0xff
1781 SpdyDataIR data_ir(1, StringPiece("\xff", 1));
1782 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1783 if (IsSpdy4()) {
1784 CompareFrame(
1785 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1786 } else {
1787 CompareFrame(
1788 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1793 const char kDescription[] = "'hello' data frame, with FIN";
1794 const unsigned char kV3FrameData[] = { // Also applies for V2.
1795 0x00, 0x00, 0x00, 0x01,
1796 0x01, 0x00, 0x00, 0x05,
1797 'h', 'e', 'l', 'l',
1800 const unsigned char kV4FrameData[] = {
1801 0x00, 0x00, 0x05, 0x00,
1802 0x01, 0x00, 0x00, 0x00,
1803 0x01, 'h', 'e', 'l',
1804 'l', 'o'
1806 SpdyDataIR data_ir(1, StringPiece("hello", 5));
1807 data_ir.set_fin(true);
1808 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1809 if (IsSpdy4()) {
1810 CompareFrame(
1811 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1812 } else {
1813 CompareFrame(
1814 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1819 const char kDescription[] = "Empty data frame";
1820 const unsigned char kV3FrameData[] = { // Also applies for V2.
1821 0x00, 0x00, 0x00, 0x01,
1822 0x00, 0x00, 0x00, 0x00,
1824 const unsigned char kV4FrameData[] = {
1825 0x00, 0x00, 0x00, 0x00,
1826 0x00, 0x00, 0x00, 0x00,
1827 0x01,
1829 SpdyDataIR data_ir(1, StringPiece());
1830 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1831 if (IsSpdy4()) {
1832 CompareFrame(
1833 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1834 } else {
1835 CompareFrame(
1836 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1839 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1840 CompareCharArraysWithHexError(
1841 kDescription,
1842 reinterpret_cast<const unsigned char*>(frame->data()),
1843 framer.GetDataFrameMinimumSize(),
1844 IsSpdy4() ? kV4FrameData : kV3FrameData,
1845 framer.GetDataFrameMinimumSize());
1849 const char kDescription[] = "Data frame with max stream ID";
1850 const unsigned char kV3FrameData[] = { // Also applies for V2.
1851 0x7f, 0xff, 0xff, 0xff,
1852 0x01, 0x00, 0x00, 0x05,
1853 'h', 'e', 'l', 'l',
1856 const unsigned char kV4FrameData[] = {
1857 0x00, 0x00, 0x05, 0x00,
1858 0x01, 0x7f, 0xff, 0xff,
1859 0xff, 'h', 'e', 'l',
1860 'l', 'o'
1862 SpdyDataIR data_ir(0x7fffffff, "hello");
1863 data_ir.set_fin(true);
1864 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1865 if (IsSpdy4()) {
1866 CompareFrame(
1867 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1868 } else {
1869 CompareFrame(
1870 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1874 if (!IsSpdy4()) {
1875 // This test does not apply to SPDY 4 because the max frame size is smaller
1876 // than 4MB.
1877 const char kDescription[] = "Large data frame";
1878 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1879 const string kData(kDataSize, 'A');
1880 const unsigned char kFrameHeader[] = {
1881 0x00, 0x00, 0x00, 0x01,
1882 0x01, 0x40, 0x00, 0x00,
1885 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1886 scoped_ptr<unsigned char[]> expected_frame_data(
1887 new unsigned char[kFrameSize]);
1888 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1889 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1891 SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
1892 data_ir.set_fin(true);
1893 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1894 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1898 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1899 if (!IsSpdy2() && !IsSpdy3()) {
1900 // SYN_STREAM unsupported in SPDY>3
1901 return;
1903 SpdyFramer framer(spdy_version_);
1904 framer.set_enable_compression(false);
1907 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1909 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1910 const unsigned char kV2FrameData[] = {
1911 0x80, spdy_version_ch_, 0x00, 0x01,
1912 0x00, 0x00, 0x00, 0x20,
1913 0x00, 0x00, 0x00, 0x01,
1914 0x00, 0x00, 0x00, 0x00,
1915 kPri, 0x00, 0x00, 0x02,
1916 0x00, 0x03, 'b', 'a',
1917 'r', 0x00, 0x03, 'f',
1918 'o', 'o', 0x00, 0x03,
1919 'f', 'o', 'o', 0x00,
1920 0x03, 'b', 'a', 'r'
1922 const unsigned char kV3FrameData[] = {
1923 0x80, spdy_version_ch_, 0x00, 0x01,
1924 0x00, 0x00, 0x00, 0x2a,
1925 0x00, 0x00, 0x00, 0x01,
1926 0x00, 0x00, 0x00, 0x00,
1927 kPri, 0x00, 0x00, 0x00,
1928 0x00, 0x02, 0x00, 0x00,
1929 0x00, 0x03, 'b', 'a',
1930 'r', 0x00, 0x00, 0x00,
1931 0x03, 'f', 'o', 'o',
1932 0x00, 0x00, 0x00, 0x03,
1933 'f', 'o', 'o', 0x00,
1934 0x00, 0x00, 0x03, 'b',
1935 'a', 'r'
1937 SpdySynStreamIR syn_stream(1);
1938 syn_stream.set_priority(framer.GetLowestPriority());
1939 syn_stream.SetHeader("bar", "foo");
1940 syn_stream.SetHeader("foo", "bar");
1941 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1942 if (IsSpdy2()) {
1943 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1944 } else if (IsSpdy3()) {
1945 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1946 } else {
1947 LOG(FATAL) << "Unsupported version in test.";
1952 const char kDescription[] =
1953 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1954 "max stream ID";
1956 const unsigned char kV2FrameData[] = {
1957 0x80, spdy_version_ch_, 0x00, 0x01,
1958 0x01, 0x00, 0x00, 0x1D,
1959 0x7f, 0xff, 0xff, 0xff,
1960 0x7f, 0xff, 0xff, 0xff,
1961 0x00, 0x00, 0x00, 0x02,
1962 0x00, 0x00, 0x00, 0x03,
1963 'f', 'o', 'o', 0x00,
1964 0x03, 'f', 'o', 'o',
1965 0x00, 0x03, 'b', 'a',
1968 const unsigned char kV3FrameData[] = {
1969 0x80, spdy_version_ch_, 0x00, 0x01,
1970 0x01, 0x00, 0x00, 0x27,
1971 0x7f, 0xff, 0xff, 0xff,
1972 0x7f, 0xff, 0xff, 0xff,
1973 0x00, 0x00, 0x00, 0x00,
1974 0x00, 0x02, 0x00, 0x00,
1975 0x00, 0x00, 0x00, 0x00,
1976 0x00, 0x03, 'f', 'o',
1977 'o', 0x00, 0x00, 0x00,
1978 0x03, 'f', 'o', 'o',
1979 0x00, 0x00, 0x00, 0x03,
1980 'b', 'a', 'r'
1982 SpdySynStreamIR syn_stream(0x7fffffff);
1983 syn_stream.set_associated_to_stream_id(0x7fffffff);
1984 syn_stream.set_priority(framer.GetHighestPriority());
1985 syn_stream.set_fin(true);
1986 syn_stream.SetHeader("", "foo");
1987 syn_stream.SetHeader("foo", "bar");
1988 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1989 if (IsSpdy2()) {
1990 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1991 } else if (IsSpdy3()) {
1992 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1993 } else {
1994 LOG(FATAL) << "Unsupported version in test.";
1999 const char kDescription[] =
2000 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
2001 "max stream ID";
2003 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
2004 const unsigned char kV2FrameData[] = {
2005 0x80, spdy_version_ch_, 0x00, 0x01,
2006 0x01, 0x00, 0x00, 0x1D,
2007 0x7f, 0xff, 0xff, 0xff,
2008 0x7f, 0xff, 0xff, 0xff,
2009 kPri, 0x00, 0x00, 0x02,
2010 0x00, 0x03, 'b', 'a',
2011 'r', 0x00, 0x03, 'f',
2012 'o', 'o', 0x00, 0x03,
2013 'f', 'o', 'o', 0x00,
2014 0x00
2016 const unsigned char kV3FrameData[] = {
2017 0x80, spdy_version_ch_, 0x00, 0x01,
2018 0x01, 0x00, 0x00, 0x27,
2019 0x7f, 0xff, 0xff, 0xff,
2020 0x7f, 0xff, 0xff, 0xff,
2021 kPri, 0x00, 0x00, 0x00,
2022 0x00, 0x02, 0x00, 0x00,
2023 0x00, 0x03, 'b', 'a',
2024 'r', 0x00, 0x00, 0x00,
2025 0x03, 'f', 'o', 'o',
2026 0x00, 0x00, 0x00, 0x03,
2027 'f', 'o', 'o', 0x00,
2028 0x00, 0x00, 0x00
2030 SpdySynStreamIR syn_stream(0x7fffffff);
2031 syn_stream.set_associated_to_stream_id(0x7fffffff);
2032 syn_stream.set_priority(1);
2033 syn_stream.set_fin(true);
2034 syn_stream.SetHeader("bar", "foo");
2035 syn_stream.SetHeader("foo", "");
2036 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2037 if (IsSpdy2()) {
2038 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2039 } else if (IsSpdy3()) {
2040 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2041 } else {
2042 LOG(FATAL) << "Unsupported version in test.";
2047 // TODO(phajdan.jr): Clean up after we no longer need
2048 // to workaround http://crbug.com/139744.
2049 #if !defined(USE_SYSTEM_ZLIB)
2050 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2051 if (!IsSpdy2() && !IsSpdy3()) {
2052 // SYN_STREAM not supported for SPDY>3
2053 return;
2055 SpdyFramer framer(spdy_version_);
2056 framer.set_enable_compression(true);
2059 const char kDescription[] =
2060 "SYN_STREAM frame, low pri, no FIN";
2061 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2063 const unsigned char kV2FrameData[] = {
2064 0x80, spdy_version_ch_, 0x00, 0x01,
2065 0x00, 0x00, 0x00, 0x36,
2066 0x00, 0x00, 0x00, 0x01,
2067 0x00, 0x00, 0x00, 0x00,
2068 0x80, 0x00, 0x38, 0xea,
2069 0xdf, 0xa2, 0x51, 0xb2,
2070 0x62, 0x60, 0x62, 0x60,
2071 0x4e, 0x4a, 0x2c, 0x62,
2072 0x60, 0x06, 0x08, 0xa0,
2073 0xb4, 0xfc, 0x7c, 0x80,
2074 0x00, 0x62, 0x60, 0x4e,
2075 0xcb, 0xcf, 0x67, 0x60,
2076 0x06, 0x08, 0xa0, 0xa4,
2077 0xc4, 0x22, 0x80, 0x00,
2078 0x02, 0x00, 0x00, 0x00,
2079 0xff, 0xff,
2081 const unsigned char kV3FrameData[] = {
2082 0x80, spdy_version_ch_, 0x00, 0x01,
2083 0x00, 0x00, 0x00, 0x37,
2084 0x00, 0x00, 0x00, 0x01,
2085 0x00, 0x00, 0x00, 0x00,
2086 0x80, 0x00, 0x38, 0xEA,
2087 0xE3, 0xC6, 0xA7, 0xC2,
2088 0x02, 0xE5, 0x0E, 0x50,
2089 0xC2, 0x4B, 0x4A, 0x04,
2090 0xE5, 0x0B, 0x66, 0x80,
2091 0x00, 0x4A, 0xCB, 0xCF,
2092 0x07, 0x08, 0x20, 0x10,
2093 0x95, 0x96, 0x9F, 0x0F,
2094 0xA2, 0x00, 0x02, 0x28,
2095 0x29, 0xB1, 0x08, 0x20,
2096 0x80, 0x00, 0x00, 0x00,
2097 0x00, 0xFF, 0xFF,
2099 const unsigned char kV2SIMDFrameData[] = {
2100 0x80, spdy_version_ch_, 0x00, 0x01,
2101 0x00, 0x00, 0x00, 0x33,
2102 0x00, 0x00, 0x00, 0x01,
2103 0x00, 0x00, 0x00, 0x00,
2104 0x80, 0x00, 0x38, 0xea,
2105 0xdf, 0xa2, 0x51, 0xb2,
2106 0x62, 0x60, 0x62, 0x60,
2107 0x4e, 0x4a, 0x2c, 0x62,
2108 0x60, 0x06, 0x08, 0xa0,
2109 0xb4, 0xfc, 0x7c, 0x80,
2110 0x00, 0x62, 0x60, 0x06,
2111 0x13, 0x00, 0x01, 0x94,
2112 0x94, 0x58, 0x04, 0x10,
2113 0x40, 0x00, 0x00, 0x00,
2114 0x00, 0xff, 0xff,
2116 const unsigned char kV3SIMDFrameData[] = {
2117 0x80, spdy_version_ch_, 0x00, 0x01,
2118 0x00, 0x00, 0x00, 0x32,
2119 0x00, 0x00, 0x00, 0x01,
2120 0x00, 0x00, 0x00, 0x00,
2121 0x80, 0x00, 0x38, 0xea,
2122 0xe3, 0xc6, 0xa7, 0xc2,
2123 0x02, 0xe5, 0x0e, 0x50,
2124 0xc2, 0x4b, 0x4a, 0x04,
2125 0xe5, 0x0b, 0x66, 0x80,
2126 0x00, 0x4a, 0xcb, 0xcf,
2127 0x07, 0x08, 0x20, 0x24,
2128 0x0a, 0x20, 0x80, 0x92,
2129 0x12, 0x8b, 0x00, 0x02,
2130 0x08, 0x00, 0x00, 0x00,
2131 0xff, 0xff,
2134 SpdySynStreamIR syn_stream(1);
2135 syn_stream.set_priority(priority);
2136 syn_stream.SetHeader("bar", "foo");
2137 syn_stream.SetHeader("foo", "bar");
2138 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2139 const unsigned char* frame_data =
2140 reinterpret_cast<const unsigned char*>(frame->data());
2141 if (IsSpdy2()) {
2142 // Try comparing with SIMD version, if that fails, do a failing check
2143 // with pretty printing against non-SIMD version
2144 if (memcmp(frame_data,
2145 kV2SIMDFrameData,
2146 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2147 CompareCharArraysWithHexError(kDescription,
2148 frame_data,
2149 frame->size(),
2150 kV2FrameData,
2151 arraysize(kV2FrameData));
2153 } else if (IsSpdy3()) {
2154 if (memcmp(frame_data,
2155 kV3SIMDFrameData,
2156 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2157 CompareCharArraysWithHexError(kDescription,
2158 frame_data,
2159 frame->size(),
2160 kV3FrameData,
2161 arraysize(kV3FrameData));
2163 } else {
2164 LOG(FATAL) << "Unsupported version in test.";
2168 #endif // !defined(USE_SYSTEM_ZLIB)
2170 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2171 if (spdy_version_ > SPDY3) {
2172 // SYN_REPLY unsupported in SPDY>3
2173 return;
2175 SpdyFramer framer(spdy_version_);
2176 framer.set_enable_compression(false);
2179 const char kDescription[] = "SYN_REPLY frame, no FIN";
2181 const unsigned char kV2FrameData[] = {
2182 0x80, spdy_version_ch_, 0x00, 0x02,
2183 0x00, 0x00, 0x00, 0x1C,
2184 0x00, 0x00, 0x00, 0x01,
2185 0x00, 0x00, 0x00, 0x02,
2186 0x00, 0x03, 'b', 'a',
2187 'r', 0x00, 0x03, 'f',
2188 'o', 'o', 0x00, 0x03,
2189 'f', 'o', 'o', 0x00,
2190 0x03, 'b', 'a', 'r'
2192 const unsigned char kV3FrameData[] = {
2193 0x80, spdy_version_ch_, 0x00, 0x02,
2194 0x00, 0x00, 0x00, 0x24,
2195 0x00, 0x00, 0x00, 0x01,
2196 0x00, 0x00, 0x00, 0x02,
2197 0x00, 0x00, 0x00, 0x03,
2198 'b', 'a', 'r', 0x00,
2199 0x00, 0x00, 0x03, 'f',
2200 'o', 'o', 0x00, 0x00,
2201 0x00, 0x03, 'f', 'o',
2202 'o', 0x00, 0x00, 0x00,
2203 0x03, 'b', 'a', 'r'
2205 SpdySynReplyIR syn_reply(1);
2206 syn_reply.SetHeader("bar", "foo");
2207 syn_reply.SetHeader("foo", "bar");
2208 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2209 if (IsSpdy2()) {
2210 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2211 } else if (IsSpdy3()) {
2212 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2213 } else {
2214 LOG(FATAL) << "Unsupported version in test.";
2219 const char kDescription[] =
2220 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2222 const unsigned char kV2FrameData[] = {
2223 0x80, spdy_version_ch_, 0x00, 0x02,
2224 0x01, 0x00, 0x00, 0x19,
2225 0x7f, 0xff, 0xff, 0xff,
2226 0x00, 0x00, 0x00, 0x02,
2227 0x00, 0x00, 0x00, 0x03,
2228 'f', 'o', 'o', 0x00,
2229 0x03, 'f', 'o', 'o',
2230 0x00, 0x03, 'b', 'a',
2233 const unsigned char kV3FrameData[] = {
2234 0x80, spdy_version_ch_, 0x00, 0x02,
2235 0x01, 0x00, 0x00, 0x21,
2236 0x7f, 0xff, 0xff, 0xff,
2237 0x00, 0x00, 0x00, 0x02,
2238 0x00, 0x00, 0x00, 0x00,
2239 0x00, 0x00, 0x00, 0x03,
2240 'f', 'o', 'o', 0x00,
2241 0x00, 0x00, 0x03, 'f',
2242 'o', 'o', 0x00, 0x00,
2243 0x00, 0x03, 'b', 'a',
2246 SpdySynReplyIR syn_reply(0x7fffffff);
2247 syn_reply.set_fin(true);
2248 syn_reply.SetHeader("", "foo");
2249 syn_reply.SetHeader("foo", "bar");
2250 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2251 if (IsSpdy2()) {
2252 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2253 } else if (IsSpdy3()) {
2254 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2255 } else {
2256 LOG(FATAL) << "Unsupported version in test.";
2261 const char kDescription[] =
2262 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2264 const unsigned char kV2FrameData[] = {
2265 0x80, spdy_version_ch_, 0x00, 0x02,
2266 0x01, 0x00, 0x00, 0x19,
2267 0x7f, 0xff, 0xff, 0xff,
2268 0x00, 0x00, 0x00, 0x02,
2269 0x00, 0x03, 'b', 'a',
2270 'r', 0x00, 0x03, 'f',
2271 'o', 'o', 0x00, 0x03,
2272 'f', 'o', 'o', 0x00,
2273 0x00
2275 const unsigned char kV3FrameData[] = {
2276 0x80, spdy_version_ch_, 0x00, 0x02,
2277 0x01, 0x00, 0x00, 0x21,
2278 0x7f, 0xff, 0xff, 0xff,
2279 0x00, 0x00, 0x00, 0x02,
2280 0x00, 0x00, 0x00, 0x03,
2281 'b', 'a', 'r', 0x00,
2282 0x00, 0x00, 0x03, 'f',
2283 'o', 'o', 0x00, 0x00,
2284 0x00, 0x03, 'f', 'o',
2285 'o', 0x00, 0x00, 0x00,
2286 0x00
2288 SpdySynReplyIR syn_reply(0x7fffffff);
2289 syn_reply.set_fin(true);
2290 syn_reply.SetHeader("bar", "foo");
2291 syn_reply.SetHeader("foo", "");
2292 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2293 if (IsSpdy2()) {
2294 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2295 } else if (IsSpdy3()) {
2296 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2297 } else {
2298 LOG(FATAL) << "Unsupported version in test.";
2303 // TODO(phajdan.jr): Clean up after we no longer need
2304 // to workaround http://crbug.com/139744.
2305 #if !defined(USE_SYSTEM_ZLIB)
2306 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2307 if (spdy_version_ > SPDY3) {
2308 // SYN_REPLY unsupported in SPDY>3
2309 return;
2311 SpdyFramer framer(spdy_version_);
2312 framer.set_enable_compression(true);
2315 const char kDescription[] = "SYN_REPLY frame, no FIN";
2317 const unsigned char kV2FrameData[] = {
2318 0x80, spdy_version_ch_, 0x00, 0x02,
2319 0x00, 0x00, 0x00, 0x32,
2320 0x00, 0x00, 0x00, 0x01,
2321 0x00, 0x00, 0x38, 0xea,
2322 0xdf, 0xa2, 0x51, 0xb2,
2323 0x62, 0x60, 0x62, 0x60,
2324 0x4e, 0x4a, 0x2c, 0x62,
2325 0x60, 0x06, 0x08, 0xa0,
2326 0xb4, 0xfc, 0x7c, 0x80,
2327 0x00, 0x62, 0x60, 0x4e,
2328 0xcb, 0xcf, 0x67, 0x60,
2329 0x06, 0x08, 0xa0, 0xa4,
2330 0xc4, 0x22, 0x80, 0x00,
2331 0x02, 0x00, 0x00, 0x00,
2332 0xff, 0xff,
2334 const unsigned char kV3FrameData[] = {
2335 0x80, spdy_version_ch_, 0x00, 0x02,
2336 0x00, 0x00, 0x00, 0x31,
2337 0x00, 0x00, 0x00, 0x01,
2338 0x38, 0xea, 0xe3, 0xc6,
2339 0xa7, 0xc2, 0x02, 0xe5,
2340 0x0e, 0x50, 0xc2, 0x4b,
2341 0x4a, 0x04, 0xe5, 0x0b,
2342 0x66, 0x80, 0x00, 0x4a,
2343 0xcb, 0xcf, 0x07, 0x08,
2344 0x20, 0x10, 0x95, 0x96,
2345 0x9f, 0x0f, 0xa2, 0x00,
2346 0x02, 0x28, 0x29, 0xb1,
2347 0x08, 0x20, 0x80, 0x00,
2348 0x00, 0x00, 0x00, 0xff,
2349 0xff,
2351 const unsigned char kV2SIMDFrameData[] = {
2352 0x80, spdy_version_ch_, 0x00, 0x02,
2353 0x00, 0x00, 0x00, 0x2f,
2354 0x00, 0x00, 0x00, 0x01,
2355 0x00, 0x00, 0x38, 0xea,
2356 0xdf, 0xa2, 0x51, 0xb2,
2357 0x62, 0x60, 0x62, 0x60,
2358 0x4e, 0x4a, 0x2c, 0x62,
2359 0x60, 0x06, 0x08, 0xa0,
2360 0xb4, 0xfc, 0x7c, 0x80,
2361 0x00, 0x62, 0x60, 0x06,
2362 0x13, 0x00, 0x01, 0x94,
2363 0x94, 0x58, 0x04, 0x10,
2364 0x40, 0x00, 0x00, 0x00,
2365 0x00, 0xff, 0xff,
2367 const unsigned char kV3SIMDFrameData[] = {
2368 0x80, spdy_version_ch_, 0x00, 0x02,
2369 0x00, 0x00, 0x00, 0x2c,
2370 0x00, 0x00, 0x00, 0x01,
2371 0x38, 0xea, 0xe3, 0xc6,
2372 0xa7, 0xc2, 0x02, 0xe5,
2373 0x0e, 0x50, 0xc2, 0x4b,
2374 0x4a, 0x04, 0xe5, 0x0b,
2375 0x66, 0x80, 0x00, 0x4a,
2376 0xcb, 0xcf, 0x07, 0x08,
2377 0x20, 0x24, 0x0a, 0x20,
2378 0x80, 0x92, 0x12, 0x8b,
2379 0x00, 0x02, 0x08, 0x00,
2380 0x00, 0x00, 0xff, 0xff,
2383 SpdySynReplyIR syn_reply(1);
2384 syn_reply.SetHeader("bar", "foo");
2385 syn_reply.SetHeader("foo", "bar");
2386 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2387 const unsigned char* frame_data =
2388 reinterpret_cast<const unsigned char*>(frame->data());
2389 if (IsSpdy2()) {
2390 // Try comparing with SIMD version, if that fails, do a failing check
2391 // with pretty printing against non-SIMD version
2392 if (memcmp(frame_data,
2393 kV2SIMDFrameData,
2394 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2395 CompareCharArraysWithHexError(kDescription,
2396 frame_data,
2397 frame->size(),
2398 kV2FrameData,
2399 arraysize(kV2FrameData));
2401 } else if (IsSpdy3()) {
2402 if (memcmp(frame_data,
2403 kV3SIMDFrameData,
2404 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2405 CompareCharArraysWithHexError(kDescription,
2406 frame_data,
2407 frame->size(),
2408 kV3FrameData,
2409 arraysize(kV3FrameData));
2411 } else {
2412 LOG(FATAL) << "Unsupported version in test.";
2416 #endif // !defined(USE_SYSTEM_ZLIB)
2418 TEST_P(SpdyFramerTest, CreateRstStream) {
2419 SpdyFramer framer(spdy_version_);
2422 const char kDescription[] = "RST_STREAM frame";
2423 const unsigned char kV3FrameData[] = { // Also applies for V2.
2424 0x80, spdy_version_ch_, 0x00, 0x03,
2425 0x00, 0x00, 0x00, 0x08,
2426 0x00, 0x00, 0x00, 0x01,
2427 0x00, 0x00, 0x00, 0x01,
2429 const unsigned char kV4FrameData[] = {
2430 0x00, 0x00, 0x07, 0x03,
2431 0x00, 0x00, 0x00, 0x00,
2432 0x01, 0x00, 0x00, 0x00,
2433 0x01, 0x52, 0x53, 0x54
2435 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2436 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2437 if (IsSpdy4()) {
2438 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2439 } else {
2440 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2445 const char kDescription[] = "RST_STREAM frame with max stream ID";
2446 const unsigned char kV3FrameData[] = { // Also applies for V2.
2447 0x80, spdy_version_ch_, 0x00, 0x03,
2448 0x00, 0x00, 0x00, 0x08,
2449 0x7f, 0xff, 0xff, 0xff,
2450 0x00, 0x00, 0x00, 0x01,
2452 const unsigned char kV4FrameData[] = {
2453 0x00, 0x00, 0x04, 0x03,
2454 0x00, 0x7f, 0xff, 0xff,
2455 0xff, 0x00, 0x00, 0x00,
2456 0x01,
2458 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2459 RST_STREAM_PROTOCOL_ERROR,
2460 "");
2461 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2462 if (IsSpdy4()) {
2463 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2464 } else {
2465 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2470 const char kDescription[] = "RST_STREAM frame with max status code";
2471 const unsigned char kV3FrameData[] = { // Also applies for V2.
2472 0x80, spdy_version_ch_, 0x00, 0x03,
2473 0x00, 0x00, 0x00, 0x08,
2474 0x7f, 0xff, 0xff, 0xff,
2475 0x00, 0x00, 0x00, 0x06,
2477 const unsigned char kV4FrameData[] = {
2478 0x00, 0x00, 0x04, 0x03,
2479 0x00, 0x7f, 0xff, 0xff,
2480 0xff, 0x00, 0x00, 0x00,
2481 0x02,
2483 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2484 RST_STREAM_INTERNAL_ERROR,
2485 "");
2486 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2487 if (IsSpdy4()) {
2488 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2489 } else {
2490 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2495 TEST_P(SpdyFramerTest, CreateSettings) {
2496 SpdyFramer framer(spdy_version_);
2499 const char kDescription[] = "Network byte order SETTINGS frame";
2501 const unsigned char kV2FrameData[] = {
2502 0x80, spdy_version_ch_, 0x00, 0x04,
2503 0x00, 0x00, 0x00, 0x0c,
2504 0x00, 0x00, 0x00, 0x01,
2505 0x07, 0x00, 0x00, 0x01,
2506 0x0a, 0x0b, 0x0c, 0x0d,
2508 const unsigned char kV3FrameData[] = {
2509 0x80, spdy_version_ch_, 0x00, 0x04,
2510 0x00, 0x00, 0x00, 0x0c,
2511 0x00, 0x00, 0x00, 0x01,
2512 0x01, 0x00, 0x00, 0x07,
2513 0x0a, 0x0b, 0x0c, 0x0d,
2515 const unsigned char kV4FrameData[] = {
2516 0x00, 0x00, 0x06, 0x04,
2517 0x00, 0x00, 0x00, 0x00,
2518 0x00, 0x00, 0x04, 0x0a,
2519 0x0b, 0x0c, 0x0d,
2522 uint32 kValue = 0x0a0b0c0d;
2523 SpdySettingsIR settings_ir;
2525 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2526 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2527 settings_ir.AddSetting(kId,
2528 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2529 kFlags & SETTINGS_FLAG_PERSISTED,
2530 kValue);
2532 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2533 if (IsSpdy2()) {
2534 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2535 } else if (IsSpdy3()) {
2536 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2537 } else {
2538 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2543 const char kDescription[] = "Basic SETTINGS frame";
2545 const unsigned char kV2FrameData[] = {
2546 0x80, spdy_version_ch_, 0x00, 0x04,
2547 0x00, 0x00, 0x00, 0x24,
2548 0x00, 0x00, 0x00, 0x04,
2549 0x01, 0x00, 0x00, 0x00, // 1st Setting
2550 0x00, 0x00, 0x00, 0x05,
2551 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2552 0x00, 0x00, 0x00, 0x06,
2553 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2554 0x00, 0x00, 0x00, 0x07,
2555 0x04, 0x00, 0x00, 0x00, // 4th Setting
2556 0x00, 0x00, 0x00, 0x08,
2558 const unsigned char kV3FrameData[] = {
2559 0x80, spdy_version_ch_, 0x00, 0x04,
2560 0x00, 0x00, 0x00, 0x24,
2561 0x00, 0x00, 0x00, 0x04,
2562 0x00, 0x00, 0x00, 0x01, // 1st Setting
2563 0x00, 0x00, 0x00, 0x05,
2564 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2565 0x00, 0x00, 0x00, 0x06,
2566 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2567 0x00, 0x00, 0x00, 0x07,
2568 0x00, 0x00, 0x00, 0x04, // 4th Setting
2569 0x00, 0x00, 0x00, 0x08,
2571 // These end up seemingly out of order because of the way that our internal
2572 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2573 // the wire.
2574 const unsigned char kV4FrameData[] = {
2575 0x00, 0x00, 0x18, 0x04,
2576 0x00, 0x00, 0x00, 0x00,
2577 0x00, 0x00, 0x03, // 3rd Setting
2578 0x00, 0x00, 0x00, 0x07,
2579 0x00, 0x04, // 4th Setting
2580 0x00, 0x00, 0x00, 0x08,
2581 0x00, 0x01, // 1st Setting
2582 0x00, 0x00, 0x00, 0x05,
2583 0x00, 0x02, // 2nd Setting
2584 0x00, 0x00, 0x00, 0x06,
2587 SpdySettingsIR settings_ir;
2588 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2589 false, // persist
2590 false, // persisted
2592 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2593 false, // persist
2594 false, // persisted
2596 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2597 false, // persist
2598 false, // persisted
2600 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2601 false, // persist
2602 false, // persisted
2604 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2606 if (IsSpdy2()) {
2607 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2608 } else if (IsSpdy3()) {
2609 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2610 } else {
2611 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2616 const char kDescription[] = "Empty SETTINGS frame";
2618 const unsigned char kV3FrameData[] = { // Also applies for V2.
2619 0x80, spdy_version_ch_, 0x00, 0x04,
2620 0x00, 0x00, 0x00, 0x04,
2621 0x00, 0x00, 0x00, 0x00,
2623 const unsigned char kV4FrameData[] = {
2624 0x00, 0x00, 0x00, 0x04,
2625 0x00, 0x00, 0x00, 0x00,
2626 0x00,
2628 SpdySettingsIR settings_ir;
2629 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2630 if (IsSpdy4()) {
2631 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2632 } else {
2633 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2638 TEST_P(SpdyFramerTest, CreatePingFrame) {
2639 SpdyFramer framer(spdy_version_);
2642 const char kDescription[] = "PING frame";
2643 const unsigned char kV3FrameData[] = { // Also applies for V2.
2644 0x80, spdy_version_ch_, 0x00, 0x06,
2645 0x00, 0x00, 0x00, 0x04,
2646 0x12, 0x34, 0x56, 0x78,
2648 const unsigned char kV4FrameData[] = {
2649 0x00, 0x00, 0x08, 0x06,
2650 0x00, 0x00, 0x00, 0x00,
2651 0x00, 0x12, 0x34, 0x56,
2652 0x78, 0x9a, 0xbc, 0xde,
2653 0xff,
2655 const unsigned char kV4FrameDataWithAck[] = {
2656 0x00, 0x00, 0x08, 0x06,
2657 0x01, 0x00, 0x00, 0x00,
2658 0x00, 0x12, 0x34, 0x56,
2659 0x78, 0x9a, 0xbc, 0xde,
2660 0xff,
2662 scoped_ptr<SpdyFrame> frame;
2663 if (IsSpdy4()) {
2664 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2665 SpdyPingIR ping_ir(kPingId);
2666 // Tests SpdyPingIR when the ping is not an ack.
2667 ASSERT_FALSE(ping_ir.is_ack());
2668 frame.reset(framer.SerializePing(ping_ir));
2669 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2671 // Tests SpdyPingIR when the ping is an ack.
2672 ping_ir.set_is_ack(true);
2673 frame.reset(framer.SerializePing(ping_ir));
2674 CompareFrame(kDescription, *frame,
2675 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2677 } else {
2678 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2679 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2684 TEST_P(SpdyFramerTest, CreateGoAway) {
2685 SpdyFramer framer(spdy_version_);
2688 const char kDescription[] = "GOAWAY frame";
2689 const unsigned char kV2FrameData[] = {
2690 0x80, spdy_version_ch_, 0x00, 0x07,
2691 0x00, 0x00, 0x00, 0x04,
2692 0x00, 0x00, 0x00, 0x00, // Stream Id
2694 const unsigned char kV3FrameData[] = {
2695 0x80, spdy_version_ch_, 0x00, 0x07,
2696 0x00, 0x00, 0x00, 0x08,
2697 0x00, 0x00, 0x00, 0x00, // Stream Id
2698 0x00, 0x00, 0x00, 0x00, // Status
2700 const unsigned char kV4FrameData[] = {
2701 0x00, 0x00, 0x0a, 0x07,
2702 0x00, 0x00, 0x00, 0x00,
2703 0x00, 0x00, 0x00, 0x00, // Stream id
2704 0x00, 0x00, 0x00, 0x00, // Status
2705 0x00, 0x47, 0x41, // Opaque Description
2707 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2708 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2709 if (IsSpdy2()) {
2710 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2711 } else if (IsSpdy3()) {
2712 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2713 } else {
2714 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2719 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2720 const unsigned char kV2FrameData[] = {
2721 0x80, spdy_version_ch_, 0x00, 0x07,
2722 0x00, 0x00, 0x00, 0x04,
2723 0x7f, 0xff, 0xff, 0xff, // Stream Id
2725 const unsigned char kV3FrameData[] = {
2726 0x80, spdy_version_ch_, 0x00, 0x07,
2727 0x00, 0x00, 0x00, 0x08,
2728 0x7f, 0xff, 0xff, 0xff, // Stream Id
2729 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2731 const unsigned char kV4FrameData[] = {
2732 0x00, 0x00, 0x0a, 0x07,
2733 0x00, 0x00, 0x00, 0x00,
2734 0x00, 0x7f, 0xff, 0xff, // Stream Id
2735 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2736 0x02, 0x47, 0x41, // Opaque Description
2738 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2739 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2740 if (IsSpdy2()) {
2741 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2742 } else if (IsSpdy3()) {
2743 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2744 } else {
2745 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2750 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2751 SpdyFramer framer(spdy_version_);
2752 framer.set_enable_compression(false);
2755 const char kDescription[] = "HEADERS frame, no FIN";
2757 const unsigned char kV2FrameData[] = {
2758 0x80, spdy_version_ch_, 0x00, 0x08,
2759 0x00, 0x00, 0x00, 0x1C,
2760 0x00, 0x00, 0x00, 0x01,
2761 0x00, 0x00, 0x00, 0x02,
2762 0x00, 0x03, 'b', 'a',
2763 'r', 0x00, 0x03, 'f',
2764 'o', 'o', 0x00, 0x03,
2765 'f', 'o', 'o', 0x00,
2766 0x03, 'b', 'a', 'r'
2768 const unsigned char kV3FrameData[] = {
2769 0x80, spdy_version_ch_, 0x00, 0x08,
2770 0x00, 0x00, 0x00, 0x24,
2771 0x00, 0x00, 0x00, 0x01,
2772 0x00, 0x00, 0x00, 0x02,
2773 0x00, 0x00, 0x00, 0x03,
2774 'b', 'a', 'r', 0x00,
2775 0x00, 0x00, 0x03, 'f',
2776 'o', 'o', 0x00, 0x00,
2777 0x00, 0x03, 'f', 'o',
2778 'o', 0x00, 0x00, 0x00,
2779 0x03, 'b', 'a', 'r'
2781 const unsigned char kV4FrameData[] = {
2782 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2783 0x04, 0x00, 0x00, 0x00, // Stream 1
2784 0x01, 0x00, 0x03, 0x62, // @.ba
2785 0x61, 0x72, 0x03, 0x66, // r.fo
2786 0x6f, 0x6f, 0x00, 0x03, // o@.f
2787 0x66, 0x6f, 0x6f, 0x03, // oo.b
2788 0x62, 0x61, 0x72, // ar
2790 SpdyHeadersIR headers_ir(1);
2791 headers_ir.SetHeader("bar", "foo");
2792 headers_ir.SetHeader("foo", "bar");
2793 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2794 if (IsSpdy2()) {
2795 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2796 } else if (IsSpdy3()) {
2797 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2798 } else {
2799 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2804 const char kDescription[] =
2805 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2807 const unsigned char kV2FrameData[] = {
2808 0x80, spdy_version_ch_, 0x00, 0x08,
2809 0x01, 0x00, 0x00, 0x19,
2810 0x7f, 0xff, 0xff, 0xff,
2811 0x00, 0x00, 0x00, 0x02,
2812 0x00, 0x00, 0x00, 0x03,
2813 'f', 'o', 'o', 0x00,
2814 0x03, 'f', 'o', 'o',
2815 0x00, 0x03, 'b', 'a',
2818 const unsigned char kV3FrameData[] = {
2819 0x80, spdy_version_ch_, 0x00, 0x08,
2820 0x01, 0x00, 0x00, 0x21,
2821 0x7f, 0xff, 0xff, 0xff,
2822 0x00, 0x00, 0x00, 0x02,
2823 0x00, 0x00, 0x00, 0x00,
2824 0x00, 0x00, 0x00, 0x03,
2825 'f', 'o', 'o', 0x00,
2826 0x00, 0x00, 0x03, 'f',
2827 'o', 'o', 0x00, 0x00,
2828 0x00, 0x03, 'b', 'a',
2831 const unsigned char kV4FrameData[] = {
2832 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2833 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2834 0xff, 0x00, 0x00, 0x03, // @..
2835 0x66, 0x6f, 0x6f, 0x00, // foo@
2836 0x03, 0x66, 0x6f, 0x6f, // .foo
2837 0x03, 0x62, 0x61, 0x72, // .bar
2839 SpdyHeadersIR headers_ir(0x7fffffff);
2840 headers_ir.set_fin(true);
2841 headers_ir.SetHeader("", "foo");
2842 headers_ir.SetHeader("foo", "bar");
2843 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2844 if (IsSpdy2()) {
2845 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2846 } else if (IsSpdy3()) {
2847 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2848 } else {
2849 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2854 const char kDescription[] =
2855 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2857 const unsigned char kV2FrameData[] = {
2858 0x80, spdy_version_ch_, 0x00, 0x08,
2859 0x01, 0x00, 0x00, 0x19,
2860 0x7f, 0xff, 0xff, 0xff,
2861 0x00, 0x00, 0x00, 0x02,
2862 0x00, 0x03, 'b', 'a',
2863 'r', 0x00, 0x03, 'f',
2864 'o', 'o', 0x00, 0x03,
2865 'f', 'o', 'o', 0x00,
2866 0x00
2868 const unsigned char kV3FrameData[] = {
2869 0x80, spdy_version_ch_, 0x00, 0x08,
2870 0x01, 0x00, 0x00, 0x21,
2871 0x7f, 0xff, 0xff, 0xff,
2872 0x00, 0x00, 0x00, 0x02,
2873 0x00, 0x00, 0x00, 0x03,
2874 'b', 'a', 'r', 0x00,
2875 0x00, 0x00, 0x03, 'f',
2876 'o', 'o', 0x00, 0x00,
2877 0x00, 0x03, 'f', 'o',
2878 'o', 0x00, 0x00, 0x00,
2879 0x00
2881 const unsigned char kV4FrameData[] = {
2882 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2883 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2884 0xff, 0x00, 0x03, 0x62, // @.b
2885 0x61, 0x72, 0x03, 0x66, // ar.f
2886 0x6f, 0x6f, 0x00, 0x03, // oo@.
2887 0x66, 0x6f, 0x6f, 0x00, // foo.
2889 SpdyHeadersIR headers_ir(0x7fffffff);
2890 headers_ir.set_fin(true);
2891 headers_ir.SetHeader("bar", "foo");
2892 headers_ir.SetHeader("foo", "");
2893 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2894 if (IsSpdy2()) {
2895 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2896 } else if (IsSpdy3()) {
2897 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2898 } else {
2899 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2904 const char kDescription[] =
2905 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2907 const unsigned char kV4FrameData[] = {
2908 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2909 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2910 0xff, 0x00, 0x00, 0x00, // parent stream
2911 0x00, 0xdb, // weight
2912 0x00, 0x03, 0x62, 0x61, // @.ba
2913 0x72, 0x03, 0x66, 0x6f, // r.fo
2914 0x6f, 0x00, 0x03, 0x66, // o@.f
2915 0x6f, 0x6f, 0x00, // oo.
2917 SpdyHeadersIR headers_ir(0x7fffffff);
2918 headers_ir.set_fin(true);
2919 headers_ir.set_priority(1);
2920 headers_ir.set_has_priority(true);
2921 headers_ir.SetHeader("bar", "foo");
2922 headers_ir.SetHeader("foo", "");
2923 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2924 if (IsSpdy2() || IsSpdy3()) {
2925 // HEADERS with priority not supported.
2926 } else {
2927 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2932 const char kDescription[] =
2933 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2935 const unsigned char kV4FrameData[] = {
2936 0x00, 0x00, 0x15, 0x01, // Headers
2937 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2938 // 0x7fffffff
2939 0xff, 0x05, 0x00, 0x00, // Pad length field
2940 0x03, 0x66, 0x6f, 0x6f, // .foo
2941 0x00, 0x03, 0x66, 0x6f, // @.fo
2942 0x6f, 0x03, 0x62, 0x61, // o.ba
2943 0x72, // r
2944 // Padding payload
2945 0x00, 0x00, 0x00, 0x00, 0x00,
2947 SpdyHeadersIR headers_ir(0x7fffffff);
2948 headers_ir.set_fin(true);
2949 headers_ir.SetHeader("", "foo");
2950 headers_ir.SetHeader("foo", "bar");
2951 headers_ir.set_padding_len(6);
2952 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2953 if (IsSpdy2() || IsSpdy3()) {
2954 // Padding is not supported.
2955 } else {
2956 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2961 // TODO(phajdan.jr): Clean up after we no longer need
2962 // to workaround http://crbug.com/139744.
2963 #if !defined(USE_SYSTEM_ZLIB)
2964 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2965 SpdyFramer framer(spdy_version_);
2966 framer.set_enable_compression(true);
2969 const char kDescription[] = "HEADERS frame, no FIN";
2971 const unsigned char kV2FrameData[] = {
2972 0x80, spdy_version_ch_, 0x00, 0x08,
2973 0x00, 0x00, 0x00, 0x32,
2974 0x00, 0x00, 0x00, 0x01,
2975 0x00, 0x00, 0x38, 0xea,
2976 0xdf, 0xa2, 0x51, 0xb2,
2977 0x62, 0x60, 0x62, 0x60,
2978 0x4e, 0x4a, 0x2c, 0x62,
2979 0x60, 0x06, 0x08, 0xa0,
2980 0xb4, 0xfc, 0x7c, 0x80,
2981 0x00, 0x62, 0x60, 0x4e,
2982 0xcb, 0xcf, 0x67, 0x60,
2983 0x06, 0x08, 0xa0, 0xa4,
2984 0xc4, 0x22, 0x80, 0x00,
2985 0x02, 0x00, 0x00, 0x00,
2986 0xff, 0xff,
2988 const unsigned char kV3FrameData[] = {
2989 0x80, spdy_version_ch_, 0x00, 0x08,
2990 0x00, 0x00, 0x00, 0x31,
2991 0x00, 0x00, 0x00, 0x01,
2992 0x38, 0xea, 0xe3, 0xc6,
2993 0xa7, 0xc2, 0x02, 0xe5,
2994 0x0e, 0x50, 0xc2, 0x4b,
2995 0x4a, 0x04, 0xe5, 0x0b,
2996 0x66, 0x80, 0x00, 0x4a,
2997 0xcb, 0xcf, 0x07, 0x08,
2998 0x20, 0x10, 0x95, 0x96,
2999 0x9f, 0x0f, 0xa2, 0x00,
3000 0x02, 0x28, 0x29, 0xb1,
3001 0x08, 0x20, 0x80, 0x00,
3002 0x00, 0x00, 0x00, 0xff,
3003 0xff,
3005 const unsigned char kV2SIMDFrameData[] = {
3006 0x80, spdy_version_ch_, 0x00, 0x08,
3007 0x00, 0x00, 0x00, 0x2f,
3008 0x00, 0x00, 0x00, 0x01,
3009 0x00, 0x00, 0x38, 0xea,
3010 0xdf, 0xa2, 0x51, 0xb2,
3011 0x62, 0x60, 0x62, 0x60,
3012 0x4e, 0x4a, 0x2c, 0x62,
3013 0x60, 0x06, 0x08, 0xa0,
3014 0xb4, 0xfc, 0x7c, 0x80,
3015 0x00, 0x62, 0x60, 0x06,
3016 0x13, 0x00, 0x01, 0x94,
3017 0x94, 0x58, 0x04, 0x10,
3018 0x40, 0x00, 0x00, 0x00,
3019 0x00, 0xff, 0xff,
3021 const unsigned char kV3SIMDFrameData[] = {
3022 0x80, spdy_version_ch_, 0x00, 0x08,
3023 0x00, 0x00, 0x00, 0x2c,
3024 0x00, 0x00, 0x00, 0x01,
3025 0x38, 0xea, 0xe3, 0xc6,
3026 0xa7, 0xc2, 0x02, 0xe5,
3027 0x0e, 0x50, 0xc2, 0x4b,
3028 0x4a, 0x04, 0xe5, 0x0b,
3029 0x66, 0x80, 0x00, 0x4a,
3030 0xcb, 0xcf, 0x07, 0x08,
3031 0x20, 0x24, 0x0a, 0x20,
3032 0x80, 0x92, 0x12, 0x8b,
3033 0x00, 0x02, 0x08, 0x00,
3034 0x00, 0x00, 0xff, 0xff,
3037 SpdyHeadersIR headers_ir(1);
3038 headers_ir.SetHeader("bar", "foo");
3039 headers_ir.SetHeader("foo", "bar");
3040 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3041 const unsigned char* frame_data =
3042 reinterpret_cast<const unsigned char*>(frame->data());
3043 if (IsSpdy2()) {
3044 // Try comparing with SIMD version, if that fails, do a failing check
3045 // with pretty printing against non-SIMD version
3046 if (memcmp(frame_data,
3047 kV2SIMDFrameData,
3048 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3049 CompareCharArraysWithHexError(kDescription,
3050 frame_data,
3051 frame->size(),
3052 kV2FrameData,
3053 arraysize(kV2FrameData));
3055 } else if (IsSpdy3()) {
3056 if (memcmp(frame_data,
3057 kV3SIMDFrameData,
3058 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3059 CompareCharArraysWithHexError(kDescription,
3060 frame_data,
3061 frame->size(),
3062 kV3FrameData,
3063 arraysize(kV3FrameData));
3065 } else {
3066 // Deflate compression doesn't apply to HPACK.
3070 #endif // !defined(USE_SYSTEM_ZLIB)
3072 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3073 SpdyFramer framer(spdy_version_);
3076 const char kDescription[] = "WINDOW_UPDATE frame";
3077 const unsigned char kV3FrameData[] = { // Also applies for V2.
3078 0x80, spdy_version_ch_, 0x00, 0x09,
3079 0x00, 0x00, 0x00, 0x08,
3080 0x00, 0x00, 0x00, 0x01,
3081 0x00, 0x00, 0x00, 0x01,
3083 const unsigned char kV4FrameData[] = {
3084 0x00, 0x00, 0x04, 0x08,
3085 0x00, 0x00, 0x00, 0x00,
3086 0x01, 0x00, 0x00, 0x00,
3087 0x01,
3089 scoped_ptr<SpdyFrame> frame(
3090 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3091 if (IsSpdy4()) {
3092 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3093 } else {
3094 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3099 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3100 const unsigned char kV3FrameData[] = { // Also applies for V2.
3101 0x80, spdy_version_ch_, 0x00, 0x09,
3102 0x00, 0x00, 0x00, 0x08,
3103 0x7f, 0xff, 0xff, 0xff,
3104 0x00, 0x00, 0x00, 0x01,
3106 const unsigned char kV4FrameData[] = {
3107 0x00, 0x00, 0x04, 0x08,
3108 0x00, 0x7f, 0xff, 0xff,
3109 0xff, 0x00, 0x00, 0x00,
3110 0x01,
3112 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3113 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3114 if (IsSpdy4()) {
3115 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3116 } else {
3117 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3122 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3123 const unsigned char kV3FrameData[] = { // Also applies for V2.
3124 0x80, spdy_version_ch_, 0x00, 0x09,
3125 0x00, 0x00, 0x00, 0x08,
3126 0x00, 0x00, 0x00, 0x01,
3127 0x7f, 0xff, 0xff, 0xff,
3129 const unsigned char kV4FrameData[] = {
3130 0x00, 0x00, 0x04, 0x08,
3131 0x00, 0x00, 0x00, 0x00,
3132 0x01, 0x7f, 0xff, 0xff,
3133 0xff,
3135 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3136 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3137 if (IsSpdy4()) {
3138 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3139 } else {
3140 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3145 TEST_P(SpdyFramerTest, SerializeBlocked) {
3146 if (spdy_version_ <= SPDY3) {
3147 return;
3150 SpdyFramer framer(spdy_version_);
3152 const char kDescription[] = "BLOCKED frame";
3153 const unsigned char kType = static_cast<unsigned char>(
3154 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3155 const unsigned char kFrameData[] = {
3156 0x00, 0x00, 0x00, kType, 0x00,
3157 0x00, 0x00, 0x00, 0x00,
3159 SpdyBlockedIR blocked_ir(0);
3160 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3161 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3164 TEST_P(SpdyFramerTest, CreateBlocked) {
3165 if (spdy_version_ <= SPDY3) {
3166 return;
3169 SpdyFramer framer(spdy_version_);
3171 const char kDescription[] = "BLOCKED frame";
3172 const SpdyStreamId kStreamId = 3;
3174 scoped_ptr<SpdySerializedFrame> frame_serialized(
3175 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3176 SpdyBlockedIR blocked_ir(kStreamId);
3177 scoped_ptr<SpdySerializedFrame> frame_created(
3178 framer.SerializeFrame(blocked_ir));
3180 CompareFrames(kDescription, *frame_serialized, *frame_created);
3183 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3184 if (spdy_version_ <= SPDY3) {
3185 return;
3189 // Test framing PUSH_PROMISE without padding.
3190 SpdyFramer framer(spdy_version_);
3191 framer.set_enable_compression(false);
3192 const char kDescription[] = "PUSH_PROMISE frame without padding";
3194 const unsigned char kFrameData[] = {
3195 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3196 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3197 0x2a, 0x00, 0x00, 0x00, // Stream 42
3198 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3199 0x61, 0x72, 0x03, 0x66, // ar.f
3200 0x6f, 0x6f, 0x00, 0x03, // oo@.
3201 0x66, 0x6f, 0x6f, 0x03, // foo.
3202 0x62, 0x61, 0x72, // bar
3205 SpdyPushPromiseIR push_promise(42, 57);
3206 push_promise.SetHeader("bar", "foo");
3207 push_promise.SetHeader("foo", "bar");
3208 scoped_ptr<SpdySerializedFrame> frame(
3209 framer.SerializePushPromise(push_promise));
3210 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3214 // Test framing PUSH_PROMISE with one byte of padding.
3215 SpdyFramer framer(spdy_version_);
3216 framer.set_enable_compression(false);
3217 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3219 const unsigned char kFrameData[] = {
3220 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3221 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3222 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3223 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3224 0x62, 0x61, 0x72, 0x03, // bar.
3225 0x66, 0x6f, 0x6f, 0x00, // foo@
3226 0x03, 0x66, 0x6f, 0x6f, // .foo
3227 0x03, 0x62, 0x61, 0x72, // .bar
3230 SpdyPushPromiseIR push_promise(42, 57);
3231 push_promise.set_padding_len(1);
3232 push_promise.SetHeader("bar", "foo");
3233 push_promise.SetHeader("foo", "bar");
3234 scoped_ptr<SpdySerializedFrame> frame(
3235 framer.SerializePushPromise(push_promise));
3236 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3240 // Test framing PUSH_PROMISE with 177 bytes of padding.
3241 SpdyFramer framer(spdy_version_);
3242 framer.set_enable_compression(false);
3243 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3245 const unsigned char kFrameData[] = {
3246 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3247 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3248 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3249 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3250 0x62, 0x61, 0x72, 0x03, // bar.
3251 0x66, 0x6f, 0x6f, 0x00, // foo@
3252 0x03, 0x66, 0x6f, 0x6f, // .foo
3253 0x03, 0x62, 0x61, 0x72, // .bar
3254 // Padding of 176 0x00(s).
3255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3272 SpdyPushPromiseIR push_promise(42, 57);
3273 push_promise.set_padding_len(177);
3274 push_promise.SetHeader("bar", "foo");
3275 push_promise.SetHeader("foo", "bar");
3276 scoped_ptr<SpdySerializedFrame> frame(
3277 framer.SerializePushPromise(push_promise));
3278 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3282 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
3283 if (spdy_version_ <= SPDY3) {
3284 return;
3287 SpdyFramer framer(spdy_version_);
3288 // Test case from https://crbug.com/464748.
3289 EXPECT_EQ(1u, framer.GetNumberRequiredContinuationFrames(2039));
3290 EXPECT_EQ(2u, framer.GetNumberRequiredContinuationFrames(2040));
3293 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3294 if (spdy_version_ <= SPDY3) {
3295 return;
3298 SpdyFramer framer(spdy_version_);
3299 framer.set_enable_compression(false);
3300 const char kDescription[] = "CONTINUATION frame";
3302 const unsigned char kFrameData[] = {
3303 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3304 0x04, 0x00, 0x00, 0x00, // end_headers = true
3305 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3306 0x61, 0x72, 0x03, 0x66, // ar.f
3307 0x6f, 0x6f, 0x00, 0x03, // oo@.
3308 0x66, 0x6f, 0x6f, 0x03, // foo.
3309 0x62, 0x61, 0x72, // bar
3312 SpdyContinuationIR continuation(42);
3313 continuation.SetHeader("bar", "foo");
3314 continuation.SetHeader("foo", "bar");
3315 continuation.set_end_headers(true);
3316 scoped_ptr<SpdySerializedFrame> frame(
3317 framer.SerializeContinuation(continuation));
3318 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3321 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3322 if (spdy_version_ <= SPDY3) {
3323 return;
3327 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3328 // padding, cannot hold all the data payload, which is overflowed to the
3329 // consecutive CONTINUATION frame.
3330 SpdyFramer framer(spdy_version_);
3331 framer.set_enable_compression(false);
3332 const char kDescription[] =
3333 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3335 const unsigned char kPartialPushPromiseFrameData[] = {
3336 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3337 0x08, 0x00, 0x00, 0x00, // PADDED
3338 0x2a, 0x00, 0x00, 0x00, // Stream 42
3339 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3340 0x78, 0x78, 0x78, 0x7f, // xxx.
3341 0x81, 0x07, 0x78, 0x78, // ..xx
3342 0x78, 0x78, 0x78, 0x78, // xxxx
3343 0x78, 0x78, 0x78, 0x78, // xxxx
3344 0x78, 0x78, 0x78, 0x78, // xxxx
3345 0x78, 0x78, 0x78, 0x78, // xxxx
3346 0x78, 0x78, 0x78, 0x78, // xxxx
3347 0x78, 0x78, 0x78, 0x78, // xxxx
3348 0x78, 0x78, 0x78, 0x78, // xxxx
3349 0x78, 0x78, 0x78, 0x78, // xxxx
3350 0x78, 0x78, 0x78, 0x78, // xxxx
3351 0x78, 0x78, 0x78, 0x78, // xxxx
3352 0x78, 0x78, 0x78, 0x78, // xxxx
3353 0x78, 0x78, 0x78, 0x78, // xxxx
3354 0x78, 0x78, 0x78, 0x78, // xxxx
3355 0x78, 0x78, 0x78, 0x78, // xxxx
3356 0x78, 0x78, 0x78, 0x78, // xxxx
3357 0x78, 0x78, 0x78, 0x78, // xxxx
3358 0x78, 0x78, 0x78, 0x78, // xxxx
3359 0x78, 0x78, 0x78, 0x78, // xxxx
3360 0x78, 0x78, 0x78, 0x78, // xxxx
3361 0x78, 0x78, 0x78, 0x78, // xxxx
3362 0x78, 0x78, // xx
3365 const unsigned char kContinuationFrameData[] = {
3366 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3367 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3368 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3369 0x78, 0x78, 0x78, 0x78, // xxxx
3370 0x78, 0x78, 0x78, 0x78, // xxxx
3371 0x78, 0x78, 0x78, 0x78, // xxxx
3372 0x78, 0x78, 0x78, 0x78, // xxxx
3373 0x78, 0x78,
3376 SpdyPushPromiseIR push_promise(42, 57);
3377 push_promise.set_padding_len(1);
3378 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3379 push_promise.SetHeader("xxx", big_value);
3380 scoped_ptr<SpdySerializedFrame> frame(
3381 framer.SerializePushPromise(push_promise));
3383 // The entire frame should look like below:
3384 // Name Length in Byte
3385 // ------------------------------------------- Begin of PUSH_PROMISE frame
3386 // PUSH_PROMISE header 9
3387 // Pad length field 1
3388 // Promised stream 4
3389 // Length field of key 2
3390 // Content of key 3
3391 // Length field of value 3
3392 // Part of big_value 16361
3393 // ------------------------------------------- Begin of CONTINUATION frame
3394 // CONTINUATION header 9
3395 // Remaining of big_value 22
3396 // ------------------------------------------- End
3398 // Length of everything listed above except big_value.
3399 int len_non_data_payload = 31;
3400 EXPECT_EQ(
3401 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3402 frame->size());
3404 // Partially compare the PUSH_PROMISE frame against the template.
3405 const unsigned char* frame_data =
3406 reinterpret_cast<const unsigned char*>(frame->data());
3407 CompareCharArraysWithHexError(kDescription,
3408 frame_data,
3409 arraysize(kPartialPushPromiseFrameData),
3410 kPartialPushPromiseFrameData,
3411 arraysize(kPartialPushPromiseFrameData));
3413 // Compare the CONTINUATION frame against the template.
3414 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3415 CompareCharArraysWithHexError(kDescription,
3416 frame_data,
3417 arraysize(kContinuationFrameData),
3418 kContinuationFrameData,
3419 arraysize(kContinuationFrameData));
3423 TEST_P(SpdyFramerTest, CreateAltSvc) {
3424 if (spdy_version_ <= SPDY3) {
3425 return;
3428 SpdyFramer framer(spdy_version_);
3430 const char kDescription[] = "ALTSVC frame";
3431 const unsigned char kType = static_cast<unsigned char>(
3432 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3433 const unsigned char kFrameData[] = {
3434 0x00, 0x00, 0x17, kType, 0x00,
3435 0x00, 0x00, 0x00, 0x03,
3436 0x00, 0x00, 0x00, 0x05,
3437 0x01, 0xbb, 0x00, 0x04, // Port = 443
3438 'p', 'i', 'd', '1', // Protocol-ID
3439 0x04, 'h', 'o', 's',
3440 't', 'o', 'r', 'i',
3441 'g', 'i', 'n',
3443 SpdyAltSvcIR altsvc_ir(3);
3444 altsvc_ir.set_max_age(5);
3445 altsvc_ir.set_port(443);
3446 altsvc_ir.set_protocol_id("pid1");
3447 altsvc_ir.set_host("host");
3448 altsvc_ir.set_origin("origin");
3449 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3450 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3453 TEST_P(SpdyFramerTest, CreatePriority) {
3454 if (spdy_version_ <= SPDY3) {
3455 return;
3458 SpdyFramer framer(spdy_version_);
3460 const char kDescription[] = "PRIORITY frame";
3461 const unsigned char kType = static_cast<unsigned char>(
3462 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3463 const unsigned char kFrameData[] = {
3464 0x00, 0x00, 0x05, kType, 0x00,
3465 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3466 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3467 0x10, // Weight = 16
3469 SpdyPriorityIR priority_ir(2, 1, 16, true);
3470 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3471 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3472 SpdyPriorityIR priority2(2);
3473 priority2.set_parent_stream_id(1);
3474 priority2.set_weight(16);
3475 priority2.set_exclusive(true);
3476 frame.reset(framer.SerializeFrame(priority2));
3477 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3480 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3481 if (spdy_version_ > SPDY3) {
3482 // SYN_STREAM not supported in SPDY>3
3483 return;
3485 SpdyFramer framer(spdy_version_);
3486 SpdySynStreamIR syn_stream(1);
3487 syn_stream.set_priority(1);
3488 syn_stream.SetHeader("aa", "vv");
3489 syn_stream.SetHeader("bb", "ww");
3490 SpdyHeaderBlock headers = syn_stream.name_value_block();
3491 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3492 EXPECT_TRUE(control_frame.get() != NULL);
3493 TestSpdyVisitor visitor(spdy_version_);
3494 visitor.use_compression_ = true;
3495 visitor.SimulateInFramer(
3496 reinterpret_cast<unsigned char*>(control_frame->data()),
3497 control_frame->size());
3498 EXPECT_EQ(1, visitor.syn_frame_count_);
3499 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3502 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3503 if (spdy_version_ > SPDY3) {
3504 return;
3506 SpdyFramer framer(spdy_version_);
3507 SpdySynReplyIR syn_reply(1);
3508 syn_reply.SetHeader("alpha", "beta");
3509 syn_reply.SetHeader("gamma", "delta");
3510 SpdyHeaderBlock headers = syn_reply.name_value_block();
3511 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3512 EXPECT_TRUE(control_frame.get() != NULL);
3513 TestSpdyVisitor visitor(spdy_version_);
3514 visitor.use_compression_ = true;
3515 visitor.SimulateInFramer(
3516 reinterpret_cast<unsigned char*>(control_frame->data()),
3517 control_frame->size());
3518 if (IsSpdy4()) {
3519 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3520 EXPECT_EQ(1, visitor.headers_frame_count_);
3521 } else {
3522 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3523 EXPECT_EQ(0, visitor.headers_frame_count_);
3525 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3528 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3529 SpdyFramer framer(spdy_version_);
3530 SpdyHeadersIR headers_ir(1);
3531 headers_ir.SetHeader("alpha", "beta");
3532 headers_ir.SetHeader("gamma", "delta");
3533 SpdyHeaderBlock headers = headers_ir.name_value_block();
3534 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3535 EXPECT_TRUE(control_frame.get() != NULL);
3536 TestSpdyVisitor visitor(spdy_version_);
3537 visitor.use_compression_ = true;
3538 visitor.SimulateInFramer(
3539 reinterpret_cast<unsigned char*>(control_frame->data()),
3540 control_frame->size());
3541 EXPECT_EQ(1, visitor.headers_frame_count_);
3542 // control_frame_header_data_count_ depends on the random sequence
3543 // produced by rand(), so adding, removing or running single tests
3544 // alters this value. The best we can do is assert that it happens
3545 // at least twice.
3546 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3547 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3548 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3549 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3552 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3553 SpdyFramer framer(spdy_version_);
3554 SpdyHeadersIR headers_ir(1);
3555 headers_ir.set_fin(true);
3556 headers_ir.SetHeader("alpha", "beta");
3557 headers_ir.SetHeader("gamma", "delta");
3558 SpdyHeaderBlock headers = headers_ir.name_value_block();
3559 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3560 EXPECT_TRUE(control_frame.get() != NULL);
3561 TestSpdyVisitor visitor(spdy_version_);
3562 visitor.use_compression_ = true;
3563 visitor.SimulateInFramer(
3564 reinterpret_cast<unsigned char*>(control_frame->data()),
3565 control_frame->size());
3566 EXPECT_EQ(1, visitor.headers_frame_count_);
3567 // control_frame_header_data_count_ depends on the random sequence
3568 // produced by rand(), so adding, removing or running single tests
3569 // alters this value. The best we can do is assert that it happens
3570 // at least twice.
3571 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3572 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3573 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3574 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3577 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3578 if (spdy_version_ > SPDY3) {
3579 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3580 return;
3582 // First find the size of the header value in order to just reach the control
3583 // frame max size.
3584 SpdyFramer framer(spdy_version_);
3585 framer.set_enable_compression(false);
3586 SpdySynStreamIR syn_stream(1);
3587 syn_stream.set_priority(1);
3588 syn_stream.SetHeader("aa", "");
3589 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3590 const size_t kBigValueSize =
3591 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3593 // Create a frame at exactly that size.
3594 string big_value(kBigValueSize, 'x');
3595 syn_stream.SetHeader("aa", big_value);
3596 control_frame.reset(framer.SerializeSynStream(syn_stream));
3597 EXPECT_TRUE(control_frame.get() != NULL);
3598 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3599 control_frame->size());
3601 TestSpdyVisitor visitor(spdy_version_);
3602 visitor.SimulateInFramer(
3603 reinterpret_cast<unsigned char*>(control_frame->data()),
3604 control_frame->size());
3605 EXPECT_TRUE(visitor.header_buffer_valid_);
3606 EXPECT_EQ(0, visitor.error_count_);
3607 EXPECT_EQ(1, visitor.syn_frame_count_);
3608 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3609 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3610 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3613 // This test is disabled because Chromium is willing to accept control frames up
3614 // to the maximum size allowed by the specification, and SpdyFrameBuilder is not
3615 // capable of building larger frames.
3616 TEST_P(SpdyFramerTest, DISABLED_ControlFrameTooLarge) {
3617 if (spdy_version_ > SPDY3) {
3618 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3619 return;
3621 // First find the size of the header value in order to just reach the control
3622 // frame max size.
3623 SpdyFramer framer(spdy_version_);
3624 framer.set_enable_compression(false);
3625 SpdySynStreamIR syn_stream(1);
3626 syn_stream.SetHeader("aa", "");
3627 syn_stream.set_priority(1);
3628 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3629 const size_t kBigValueSize =
3630 SpdyConstants::GetFrameMaximumSize(spdy_version_) -
3631 control_frame->size() + 1;
3633 // Create a frame at exatly that size.
3634 string big_value(kBigValueSize, 'x');
3635 syn_stream.SetHeader("aa", big_value);
3636 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3637 // neither support that in Chromium, nor do we use the same DFATAL (see
3638 // SpdyFrameBuilder::WriteFramePrefix()).
3639 control_frame.reset(framer.SerializeSynStream(syn_stream));
3641 EXPECT_TRUE(control_frame.get() != NULL);
3642 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_) + 1,
3643 control_frame->size());
3645 TestSpdyVisitor visitor(spdy_version_);
3646 visitor.SimulateInFramer(
3647 reinterpret_cast<unsigned char*>(control_frame->data()),
3648 control_frame->size());
3649 EXPECT_FALSE(visitor.header_buffer_valid_);
3650 EXPECT_EQ(1, visitor.error_count_);
3651 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3652 visitor.framer_.error_code())
3653 << SpdyFramer::ErrorCodeToString(framer.error_code());
3654 EXPECT_EQ(0, visitor.syn_frame_count_);
3655 EXPECT_EQ(0u, visitor.header_buffer_length_);
3658 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3659 if (spdy_version_ <= SPDY3) {
3660 return;
3662 SpdyFramer framer(spdy_version_);
3663 framer.set_enable_compression(false);
3664 SpdyHeadersIR headers(1);
3665 headers.set_padding_len(256);
3667 // Exact payload length will change with HPACK, but this should be long
3668 // enough to cause an overflow.
3669 const size_t kBigValueSize = kControlFrameSizeLimit;
3670 string big_value(kBigValueSize, 'x');
3671 headers.SetHeader("aa", big_value);
3672 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3673 EXPECT_TRUE(control_frame.get() != NULL);
3674 EXPECT_GT(control_frame->size(),
3675 TestSpdyVisitor::sent_control_frame_max_size());
3677 TestSpdyVisitor visitor(spdy_version_);
3678 visitor.SimulateInFramer(
3679 reinterpret_cast<unsigned char*>(control_frame->data()),
3680 control_frame->size());
3681 EXPECT_TRUE(visitor.header_buffer_valid_);
3682 EXPECT_EQ(0, visitor.error_count_);
3683 EXPECT_EQ(1, visitor.headers_frame_count_);
3684 EXPECT_EQ(16, visitor.continuation_count_);
3685 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3688 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3689 if (spdy_version_ <= SPDY3) {
3690 return;
3692 SpdyFramer framer(spdy_version_);
3693 framer.set_enable_compression(false);
3694 SpdyPushPromiseIR push_promise(1, 2);
3695 push_promise.set_padding_len(256);
3697 // Exact payload length will change with HPACK, but this should be long
3698 // enough to cause an overflow.
3699 const size_t kBigValueSize = kControlFrameSizeLimit;
3700 string big_value(kBigValueSize, 'x');
3701 push_promise.SetHeader("aa", big_value);
3702 scoped_ptr<SpdyFrame> control_frame(
3703 framer.SerializePushPromise(push_promise));
3704 EXPECT_TRUE(control_frame.get() != NULL);
3705 EXPECT_GT(control_frame->size(),
3706 TestSpdyVisitor::sent_control_frame_max_size());
3708 TestSpdyVisitor visitor(spdy_version_);
3709 visitor.SimulateInFramer(
3710 reinterpret_cast<unsigned char*>(control_frame->data()),
3711 control_frame->size());
3712 EXPECT_TRUE(visitor.header_buffer_valid_);
3713 EXPECT_EQ(0, visitor.error_count_);
3714 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3715 EXPECT_EQ(16, visitor.continuation_count_);
3716 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3719 // Check that the framer stops delivering header data chunks once the visitor
3720 // declares it doesn't want any more. This is important to guard against
3721 // "zip bomb" types of attacks.
3722 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3723 const size_t kHeaderBufferChunks = 4;
3724 const size_t kHeaderBufferSize =
3725 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3726 const size_t kBigValueSize = kHeaderBufferSize * 2;
3727 string big_value(kBigValueSize, 'x');
3728 SpdyFramer framer(spdy_version_);
3729 SpdyHeadersIR headers(1);
3730 headers.set_priority(1);
3731 headers.set_fin(true);
3732 headers.SetHeader("aa", big_value);
3733 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3734 EXPECT_TRUE(control_frame.get() != NULL);
3735 TestSpdyVisitor visitor(spdy_version_);
3736 visitor.set_header_buffer_size(kHeaderBufferSize);
3737 visitor.use_compression_ = true;
3738 visitor.SimulateInFramer(
3739 reinterpret_cast<unsigned char*>(control_frame->data()),
3740 control_frame->size());
3741 EXPECT_FALSE(visitor.header_buffer_valid_);
3742 EXPECT_EQ(1, visitor.error_count_);
3743 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3744 visitor.framer_.error_code())
3745 << SpdyFramer::ErrorCodeToString(framer.error_code());
3747 // The framer should have stoped delivering chunks after the visitor
3748 // signaled "stop" by returning false from OnControlFrameHeaderData().
3750 // control_frame_header_data_count_ depends on the random sequence
3751 // produced by rand(), so adding, removing or running single tests
3752 // alters this value. The best we can do is assert that it happens
3753 // at least kHeaderBufferChunks + 1.
3754 EXPECT_LE(kHeaderBufferChunks + 1,
3755 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3756 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3758 // The framer should not have sent half-close to the visitor.
3759 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3762 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3763 if (spdy_version_ > SPDY3) {
3764 // Deflate compression doesn't apply to HPACK.
3765 return;
3767 SpdyFramer framer(spdy_version_);
3768 framer.set_enable_compression(false);
3769 // Construct a SYN_STREAM control frame without compressing the header block,
3770 // and have the framer try to decompress it. This will cause the framer to
3771 // deal with a decompression error.
3772 SpdySynStreamIR syn_stream(1);
3773 syn_stream.set_priority(1);
3774 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3775 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3776 TestSpdyVisitor visitor(spdy_version_);
3777 visitor.use_compression_ = true;
3778 visitor.SimulateInFramer(
3779 reinterpret_cast<unsigned char*>(control_frame->data()),
3780 control_frame->size());
3781 EXPECT_EQ(1, visitor.error_count_);
3782 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3783 << SpdyFramer::ErrorCodeToString(framer.error_code());
3784 EXPECT_EQ(0u, visitor.header_buffer_length_);
3787 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3788 SpdyFramer framer(spdy_version_);
3789 // Create a GoAway frame that has a few extra bytes at the end.
3790 // We create enough overhead to overflow the framer's control frame buffer.
3791 ASSERT_LE(SpdyFramer::kControlFrameBufferSize, 250u);
3792 const size_t length = SpdyFramer::kControlFrameBufferSize + 1;
3793 const unsigned char kV3FrameData[] = { // Also applies for V2.
3794 0x80, spdy_version_ch_, 0x00, 0x07,
3795 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
3796 0x00, 0x00, 0x00, 0x00, // Stream ID
3797 0x00, 0x00, 0x00, 0x00, // Status
3800 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3801 // since it may carry opaque data. Verify that minimal length is tested.
3802 ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
3803 const size_t less_than_min_length =
3804 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3805 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3806 const unsigned char kV4FrameData[] = {
3807 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
3808 0x00, 0x00, 0x00, 0x00,
3809 0x00, 0x00, 0x00, 0x00, // Stream Id
3810 0x00, 0x00, 0x00, 0x00, // Status
3811 0x00,
3813 const size_t pad_length =
3814 length + framer.GetControlFrameHeaderSize() -
3815 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3816 string pad(pad_length, 'A');
3817 TestSpdyVisitor visitor(spdy_version_);
3819 if (IsSpdy4()) {
3820 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3821 } else {
3822 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3824 visitor.SimulateInFramer(
3825 reinterpret_cast<const unsigned char*>(pad.c_str()),
3826 pad.length());
3828 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3829 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3830 visitor.framer_.error_code())
3831 << SpdyFramer::ErrorCodeToString(framer.error_code());
3832 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3835 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3836 SpdyFramer framer(spdy_version_);
3837 SpdySettingsIR settings_ir;
3838 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3839 SetFrameLength(control_frame.get(), 0, spdy_version_);
3840 TestSpdyVisitor visitor(spdy_version_);
3841 visitor.use_compression_ = false;
3842 visitor.SimulateInFramer(
3843 reinterpret_cast<unsigned char*>(control_frame->data()),
3844 framer.GetControlFrameHeaderSize());
3845 if (spdy_version_ <= SPDY3) {
3846 // Should generate an error, since zero-len settings frames are unsupported.
3847 EXPECT_EQ(1, visitor.error_count_);
3848 } else {
3849 // Zero-len settings frames are permitted as of SPDY 4.
3850 EXPECT_EQ(0, visitor.error_count_);
3854 // Tests handling of SETTINGS frames with invalid length.
3855 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3856 SpdyFramer framer(spdy_version_);
3857 SpdySettingsIR settings_ir;
3859 // Add a setting to pad the frame so that we don't get a buffer overflow when
3860 // calling SimulateInFramer() below.
3861 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3862 false,
3863 false,
3864 0x00000002);
3865 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3866 const size_t kNewLength = 14;
3867 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3868 TestSpdyVisitor visitor(spdy_version_);
3869 visitor.use_compression_ = false;
3870 visitor.SimulateInFramer(
3871 reinterpret_cast<unsigned char*>(control_frame->data()),
3872 framer.GetControlFrameHeaderSize() + kNewLength);
3873 // Should generate an error, since its not possible to have a
3874 // settings frame of length kNewLength.
3875 EXPECT_EQ(1, visitor.error_count_);
3878 // Tests handling of SETTINGS frames larger than the frame buffer size.
3879 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3880 SpdyFramer framer(spdy_version_);
3881 SpdySettingsIR settings_ir;
3882 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3883 false, // persist
3884 false, // persisted
3886 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3887 false, // persist
3888 false, // persisted
3890 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3891 false, // persist
3892 false, // persisted
3895 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3896 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3897 control_frame->size());
3898 TestSpdyVisitor visitor(spdy_version_);
3899 visitor.use_compression_ = false;
3901 // Read all at once.
3902 visitor.SimulateInFramer(
3903 reinterpret_cast<unsigned char*>(control_frame->data()),
3904 control_frame->size());
3905 EXPECT_EQ(0, visitor.error_count_);
3906 EXPECT_EQ(3, visitor.setting_count_);
3907 if (spdy_version_ > SPDY3) {
3908 EXPECT_EQ(1, visitor.settings_ack_sent_);
3911 // Read data in small chunks.
3912 size_t framed_data = 0;
3913 size_t unframed_data = control_frame->size();
3914 size_t kReadChunkSize = 5; // Read five bytes at a time.
3915 while (unframed_data > 0) {
3916 size_t to_read = std::min(kReadChunkSize, unframed_data);
3917 visitor.SimulateInFramer(
3918 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3919 to_read);
3920 unframed_data -= to_read;
3921 framed_data += to_read;
3923 EXPECT_EQ(0, visitor.error_count_);
3924 EXPECT_EQ(3 * 2, visitor.setting_count_);
3925 if (spdy_version_ > SPDY3) {
3926 EXPECT_EQ(2, visitor.settings_ack_sent_);
3930 // Tests handling of SETTINGS frame with duplicate entries.
3931 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3932 SpdyFramer framer(spdy_version_);
3934 const unsigned char kV2FrameData[] = {
3935 0x80, spdy_version_ch_, 0x00, 0x04,
3936 0x00, 0x00, 0x00, 0x1C,
3937 0x00, 0x00, 0x00, 0x03,
3938 0x01, 0x00, 0x00, 0x00, // 1st Setting
3939 0x00, 0x00, 0x00, 0x02,
3940 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3941 0x00, 0x00, 0x00, 0x03,
3942 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3943 0x00, 0x00, 0x00, 0x03,
3945 const unsigned char kV3FrameData[] = {
3946 0x80, spdy_version_ch_, 0x00, 0x04,
3947 0x00, 0x00, 0x00, 0x1C,
3948 0x00, 0x00, 0x00, 0x03,
3949 0x00, 0x00, 0x00, 0x01, // 1st Setting
3950 0x00, 0x00, 0x00, 0x02,
3951 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3952 0x00, 0x00, 0x00, 0x03,
3953 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3954 0x00, 0x00, 0x00, 0x03,
3956 const unsigned char kV4FrameData[] = {
3957 0x00, 0x00, 0x12, 0x04,
3958 0x00, 0x00, 0x00, 0x00,
3959 0x00, 0x00, 0x01, // 1st Setting
3960 0x00, 0x00, 0x00, 0x02,
3961 0x00, 0x01, // 2nd (duplicate) Setting
3962 0x00, 0x00, 0x00, 0x03,
3963 0x00, 0x03, // 3rd (unprocessed) Setting
3964 0x00, 0x00, 0x00, 0x03,
3967 TestSpdyVisitor visitor(spdy_version_);
3968 visitor.use_compression_ = false;
3969 if (IsSpdy2()) {
3970 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3971 } else if (IsSpdy3()) {
3972 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3973 } else {
3974 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3977 if (!IsSpdy4()) {
3978 EXPECT_EQ(1, visitor.setting_count_);
3979 EXPECT_EQ(1, visitor.error_count_);
3980 } else {
3981 // In SPDY 4+, duplicate settings are allowed;
3982 // each setting replaces the previous value for that setting.
3983 EXPECT_EQ(3, visitor.setting_count_);
3984 EXPECT_EQ(0, visitor.error_count_);
3985 EXPECT_EQ(1, visitor.settings_ack_sent_);
3989 // Tests handling of SETTINGS frame with a setting we don't recognize.
3990 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3991 SpdyFramer framer(spdy_version_);
3993 const unsigned char kV2FrameData[] = {
3994 0x80, spdy_version_ch_, 0x00, 0x04,
3995 0x00, 0x00, 0x00, 0x1C,
3996 0x00, 0x00, 0x00, 0x01,
3997 0x10, 0x00, 0x00, 0x00, // 1st Setting
3998 0x00, 0x00, 0x00, 0x02,
4000 const unsigned char kV3FrameData[] = {
4001 0x80, spdy_version_ch_, 0x00, 0x04,
4002 0x00, 0x00, 0x00, 0x1C,
4003 0x00, 0x00, 0x00, 0x01,
4004 0x00, 0x00, 0x00, 0x10, // 1st Setting
4005 0x00, 0x00, 0x00, 0x02,
4007 const unsigned char kV4FrameData[] = {
4008 0x00, 0x00, 0x06, 0x04,
4009 0x00, 0x00, 0x00, 0x00,
4010 0x00, 0x00, 0x10, // 1st Setting
4011 0x00, 0x00, 0x00, 0x02,
4014 TestSpdyVisitor visitor(spdy_version_);
4015 visitor.use_compression_ = false;
4016 if (IsSpdy2()) {
4017 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4018 } else if (IsSpdy3()) {
4019 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4020 } else {
4021 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4024 if (!IsSpdy4()) {
4025 EXPECT_EQ(0, visitor.setting_count_);
4026 EXPECT_EQ(1, visitor.error_count_);
4027 } else {
4028 // In SPDY 4+, we ignore unknown settings because of extensions.
4029 EXPECT_EQ(0, visitor.setting_count_);
4030 EXPECT_EQ(0, visitor.error_count_);
4034 // Tests handling of SETTINGS frame with entries out of order.
4035 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
4036 SpdyFramer framer(spdy_version_);
4038 const unsigned char kV2FrameData[] = {
4039 0x80, spdy_version_ch_, 0x00, 0x04,
4040 0x00, 0x00, 0x00, 0x1C,
4041 0x00, 0x00, 0x00, 0x03,
4042 0x02, 0x00, 0x00, 0x00, // 1st Setting
4043 0x00, 0x00, 0x00, 0x02,
4044 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4045 0x00, 0x00, 0x00, 0x03,
4046 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4047 0x00, 0x00, 0x00, 0x03,
4049 const unsigned char kV3FrameData[] = {
4050 0x80, spdy_version_ch_, 0x00, 0x04,
4051 0x00, 0x00, 0x00, 0x1C,
4052 0x00, 0x00, 0x00, 0x03,
4053 0x00, 0x00, 0x00, 0x02, // 1st Setting
4054 0x00, 0x00, 0x00, 0x02,
4055 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4056 0x00, 0x00, 0x00, 0x03,
4057 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4058 0x00, 0x00, 0x00, 0x03,
4060 const unsigned char kV4FrameData[] = {
4061 0x00, 0x00, 0x12, 0x04,
4062 0x00, 0x00, 0x00, 0x00,
4063 0x00, 0x00, 0x02, // 1st Setting
4064 0x00, 0x00, 0x00, 0x02,
4065 0x00, 0x01, // 2nd (out of order) Setting
4066 0x00, 0x00, 0x00, 0x03,
4067 0x00, 0x03, // 3rd (unprocessed) Setting
4068 0x00, 0x00, 0x00, 0x03,
4071 TestSpdyVisitor visitor(spdy_version_);
4072 visitor.use_compression_ = false;
4073 if (IsSpdy2()) {
4074 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4075 } else if (IsSpdy3()) {
4076 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4077 } else {
4078 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4081 if (!IsSpdy4()) {
4082 EXPECT_EQ(1, visitor.setting_count_);
4083 EXPECT_EQ(1, visitor.error_count_);
4084 } else {
4085 // In SPDY 4+, settings are allowed in any order.
4086 EXPECT_EQ(3, visitor.setting_count_);
4087 EXPECT_EQ(0, visitor.error_count_);
4091 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4092 if (spdy_version_ <= SPDY3) {
4093 return;
4095 SpdyFramer framer(spdy_version_);
4097 const unsigned char kFrameData[] = {
4098 0x00, 0x00, 0x00, 0x04, 0x01,
4099 0x00, 0x00, 0x00, 0x00,
4102 TestSpdyVisitor visitor(spdy_version_);
4103 visitor.use_compression_ = false;
4104 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4106 EXPECT_EQ(0, visitor.error_count_);
4107 EXPECT_EQ(0, visitor.setting_count_);
4108 EXPECT_EQ(1, visitor.settings_ack_received_);
4111 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4112 if (spdy_version_ <= SPDY3) {
4113 return;
4116 const int kPaddingLen = 119;
4117 const char data_payload[] = "hello";
4119 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4120 SpdyFramer framer(spdy_version_);
4121 framer.set_visitor(&visitor);
4123 SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
4124 data_ir.set_padding_len(kPaddingLen);
4125 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4126 ASSERT_TRUE(frame.get() != NULL);
4128 int bytes_consumed = 0;
4130 // Send the frame header.
4131 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4132 kPaddingLen + strlen(data_payload),
4133 false));
4134 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4135 framer.ProcessInput(frame->data(),
4136 framer.GetDataFrameMinimumSize()));
4137 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4138 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4139 bytes_consumed += framer.GetDataFrameMinimumSize();
4141 // Send the padding length field.
4142 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
4143 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4144 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4145 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4146 bytes_consumed += 1;
4148 // Send the first two bytes of the data payload, i.e., "he".
4149 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4150 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4151 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4152 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4153 bytes_consumed += 2;
4155 // Send the rest three bytes of the data payload, i.e., "llo".
4156 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4157 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4158 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4159 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4160 bytes_consumed += 3;
4162 // Send the first 100 bytes of the padding payload.
4163 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
4164 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4165 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4166 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4167 bytes_consumed += 100;
4169 // Send rest of the padding payload.
4170 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
4171 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4172 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
4173 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4176 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4177 SpdyFramer framer(spdy_version_);
4178 scoped_ptr<SpdyFrame> control_frame(
4179 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4180 TestSpdyVisitor visitor(spdy_version_);
4181 visitor.SimulateInFramer(
4182 reinterpret_cast<unsigned char*>(control_frame->data()),
4183 control_frame->size());
4184 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4185 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4188 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4189 if (!IsSpdy3()) {
4190 return;
4192 SpdyFramer framer(spdy_version_);
4193 const unsigned char kV3FrameData[] = { // Also applies for V2.
4194 0x80, spdy_version_ch_, 0x00, 0x0A,
4195 0x00, 0x00, 0x00, 0x33,
4196 0x00, 0x03, 0x00, 0x00,
4197 0x00, 0x05, 'p', 'r',
4198 'o', 'o', 'f', 0x00,
4199 0x00, 0x00, 0x06, 'a',
4200 ' ', 'c', 'e', 'r',
4201 't', 0x00, 0x00, 0x00,
4202 0x0C, 'a', 'n', 'o',
4203 't', 'h', 'e', 'r',
4204 ' ', 'c', 'e', 'r',
4205 't', 0x00, 0x00, 0x00,
4206 0x0A, 'f', 'i', 'n',
4207 'a', 'l', ' ', 'c',
4208 'e', 'r', 't',
4210 TestSpdyVisitor visitor(spdy_version_);
4211 visitor.use_compression_ = false;
4212 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4213 EXPECT_EQ(0, visitor.error_count_);
4216 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4217 if (!IsSpdy3()) {
4218 return;
4220 SpdyFramer framer(spdy_version_);
4221 const unsigned char kV3FrameData[] = { // Also applies for V2.
4222 0x80, spdy_version_ch_, 0x00, 0x0A,
4223 0x00, 0x00, 0x00, 0x33,
4224 0x00, 0x03, 0x00, 0x00,
4225 0x00, 0x05, 'p', 'r',
4226 'o', 'o', 'f', 0x00,
4227 0x00, 0x00, 0x06, 'a',
4228 ' ', 'c', 'e', 'r',
4229 't', 0x00, 0x00, 0x00,
4230 0x0C, 'a', 'n', 'o',
4231 't', 'h', 'e', 'r',
4232 ' ', 'c', 'e', 'r',
4233 't', 0x00, 0x00, 0x00,
4234 0x0A, 'f', 'i', 'n',
4235 'a', 'l', ' ', 'c',
4236 'e', 'r', 't',
4238 TestSpdyVisitor visitor(spdy_version_);
4239 visitor.use_compression_ = false;
4240 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4241 arraysize(kV3FrameData));
4242 scoped_ptr<SpdyFrame> control_frame(
4243 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4244 multiple_frame_data.append(string(control_frame->data(),
4245 control_frame->size()));
4246 visitor.SimulateInFramer(
4247 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4248 multiple_frame_data.length());
4249 EXPECT_EQ(0, visitor.error_count_);
4250 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4251 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4254 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4255 if (spdy_version_ <= SPDY3) {
4256 return;
4259 SpdyFramer framer(spdy_version_);
4260 SpdyPushPromiseIR push_promise(42, 57);
4261 push_promise.SetHeader("foo", "bar");
4262 push_promise.SetHeader("bar", "foofoo");
4263 SpdyHeaderBlock headers = push_promise.name_value_block();
4264 scoped_ptr<SpdySerializedFrame> frame(
4265 framer.SerializePushPromise(push_promise));
4266 EXPECT_TRUE(frame.get() != NULL);
4267 TestSpdyVisitor visitor(spdy_version_);
4268 visitor.use_compression_ = true;
4269 visitor.SimulateInFramer(
4270 reinterpret_cast<unsigned char*>(frame->data()),
4271 frame->size());
4272 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4273 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4274 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4277 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4278 if (spdy_version_ <= SPDY3) {
4279 return;
4282 const unsigned char kInput[] = {
4283 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4284 0x00, 0x00, 0x00, 0x01, // Stream 1
4285 0x03, // Padding of 3.
4286 0x00, 0x06, 0x63, 0x6f,
4287 0x6f, 0x6b, 0x69, 0x65,
4288 0x07, 0x66, 0x6f, 0x6f,
4289 0x3d, 0x62, 0x61, 0x72,
4290 0x00, 0x00, 0x00,
4292 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4293 0x00, 0x00, 0x00, 0x01, // Stream 1
4294 0x00, 0x06, 0x63, 0x6f,
4295 0x6f, 0x6b, 0x69, 0x65,
4296 0x08, 0x62, 0x61, 0x7a,
4297 0x3d, 0x62, 0x69, 0x6e,
4298 0x67, 0x00, 0x06, 0x63,
4300 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4301 0x00, 0x00, 0x00, 0x01, // Stream 1
4302 0x6f, 0x6f, 0x6b, 0x69,
4303 0x65, 0x00, 0x00, 0x04,
4304 0x6e, 0x61, 0x6d, 0x65,
4305 0x05, 0x76, 0x61, 0x6c,
4306 0x75, 0x65,
4309 TestSpdyVisitor visitor(spdy_version_);
4310 visitor.SimulateInFramer(kInput, sizeof(kInput));
4312 EXPECT_EQ(0, visitor.error_count_);
4313 EXPECT_EQ(1, visitor.headers_frame_count_);
4314 EXPECT_EQ(2, visitor.continuation_count_);
4315 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4316 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4318 EXPECT_THAT(visitor.headers_,
4319 testing::ElementsAre(
4320 testing::Pair("cookie", "foo=bar; baz=bing; "),
4321 testing::Pair("name", "value")));
4324 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4325 if (spdy_version_ <= SPDY3) {
4326 return;
4329 const unsigned char kInput[] = {
4330 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4331 0x00, 0x00, 0x00, 0x01, // Stream 1
4332 0x00, 0x06, 0x63, 0x6f,
4333 0x6f, 0x6b, 0x69, 0x65,
4334 0x07, 0x66, 0x6f, 0x6f,
4335 0x3d, 0x62, 0x61, 0x72,
4337 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4338 0x00, 0x00, 0x00, 0x01, // Stream 1
4339 0x00, 0x06, 0x63, 0x6f,
4340 0x6f, 0x6b, 0x69, 0x65,
4341 0x08, 0x62, 0x61, 0x7a,
4342 0x3d, 0x62, 0x69, 0x6e,
4343 0x67, 0x00, 0x06, 0x63,
4345 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4346 0x00, 0x00, 0x00, 0x01, // Stream 1
4347 0x6f, 0x6f, 0x6b, 0x69,
4348 0x65, 0x00, 0x00, 0x04,
4349 0x6e, 0x61, 0x6d, 0x65,
4350 0x05, 0x76, 0x61, 0x6c,
4351 0x75, 0x65,
4354 SpdyFramer framer(spdy_version_);
4355 TestSpdyVisitor visitor(spdy_version_);
4356 visitor.SimulateInFramer(kInput, sizeof(kInput));
4358 EXPECT_EQ(0, visitor.error_count_);
4359 EXPECT_EQ(1, visitor.headers_frame_count_);
4360 EXPECT_EQ(2, visitor.continuation_count_);
4361 EXPECT_EQ(1, visitor.fin_flag_count_);
4362 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4363 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4365 EXPECT_THAT(visitor.headers_,
4366 testing::ElementsAre(
4367 testing::Pair("cookie", "foo=bar; baz=bing; "),
4368 testing::Pair("name", "value")));
4371 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4372 if (spdy_version_ <= SPDY3) {
4373 return;
4376 const unsigned char kInput[] = {
4377 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4378 0x08, 0x00, 0x00, 0x00, // PADDED
4379 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4380 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4381 0x63, 0x6f, 0x6f, 0x6b,
4382 0x69, 0x65, 0x07, 0x66,
4383 0x6f, 0x6f, 0x3d, 0x62,
4384 0x61, 0x72, 0x00, 0x00,
4386 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4387 0x00, 0x00, 0x00, 0x00,
4388 0x01, 0x00, 0x06, 0x63, // Stream 1
4389 0x6f, 0x6f, 0x6b, 0x69,
4390 0x65, 0x08, 0x62, 0x61,
4391 0x7a, 0x3d, 0x62, 0x69,
4392 0x6e, 0x67, 0x00, 0x06,
4393 0x63,
4395 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4396 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4397 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4398 0x69, 0x65, 0x00, 0x00,
4399 0x04, 0x6e, 0x61, 0x6d,
4400 0x65, 0x05, 0x76, 0x61,
4401 0x6c, 0x75, 0x65,
4404 SpdyFramer framer(spdy_version_);
4405 TestSpdyVisitor visitor(spdy_version_);
4406 visitor.SimulateInFramer(kInput, sizeof(kInput));
4408 EXPECT_EQ(0, visitor.error_count_);
4409 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4410 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4411 EXPECT_EQ(2, visitor.continuation_count_);
4412 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4413 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4415 EXPECT_THAT(visitor.headers_,
4416 testing::ElementsAre(
4417 testing::Pair("cookie", "foo=bar; baz=bing; "),
4418 testing::Pair("name", "value")));
4421 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4422 if (spdy_version_ <= SPDY3) {
4423 return;
4426 const unsigned char kInput[] = {
4427 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4428 0x00, 0x00, 0x00, 0x01, // Stream 1
4429 0x00, 0x06, 0x63, 0x6f,
4430 0x6f, 0x6b, 0x69, 0x65,
4431 0x07, 0x66, 0x6f, 0x6f,
4432 0x3d, 0x62, 0x61, 0x72,
4434 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4435 0x00, 0x00, 0x00, 0x02, // Stream 2
4436 0x00, 0x06, 0x63, 0x6f,
4437 0x6f, 0x6b, 0x69, 0x65,
4438 0x08, 0x62, 0x61, 0x7a,
4439 0x3d, 0x62, 0x69, 0x6e,
4440 0x67, 0x00, 0x06, 0x63,
4443 SpdyFramer framer(spdy_version_);
4444 TestSpdyVisitor visitor(spdy_version_);
4445 framer.set_visitor(&visitor);
4446 visitor.SimulateInFramer(kInput, sizeof(kInput));
4448 EXPECT_EQ(1, visitor.error_count_);
4449 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4450 visitor.framer_.error_code())
4451 << SpdyFramer::ErrorCodeToString(framer.error_code());
4452 EXPECT_EQ(1, visitor.headers_frame_count_);
4453 EXPECT_EQ(0, visitor.continuation_count_);
4454 EXPECT_EQ(0u, visitor.header_buffer_length_);
4457 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4458 if (spdy_version_ <= SPDY3) {
4459 return;
4462 const unsigned char kInput[] = {
4463 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4464 0x00, 0x00, 0x00, 0x01, // Stream 1
4465 0x00, 0x06, 0x63, 0x6f,
4466 0x6f, 0x6b, 0x69, 0x65,
4467 0x07, 0x66, 0x6f, 0x6f,
4468 0x3d, 0x62, 0x61, 0x72,
4471 SpdyFramer framer(spdy_version_);
4472 TestSpdyVisitor visitor(spdy_version_);
4473 framer.set_visitor(&visitor);
4474 visitor.SimulateInFramer(kInput, sizeof(kInput));
4476 EXPECT_EQ(1, visitor.error_count_);
4477 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4478 visitor.framer_.error_code())
4479 << SpdyFramer::ErrorCodeToString(framer.error_code());
4480 EXPECT_EQ(0, visitor.continuation_count_);
4481 EXPECT_EQ(0u, visitor.header_buffer_length_);
4484 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4485 if (spdy_version_ <= SPDY3) {
4486 return;
4489 const unsigned char kInput[] = {
4490 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4491 0x00, 0x00, 0x00, 0x01, // Stream 1
4492 0x00, 0x06, 0x63, 0x6f,
4493 0x6f, 0x6b, 0x69, 0x65,
4494 0x07, 0x66, 0x6f, 0x6f,
4495 0x3d, 0x62, 0x61, 0x72,
4497 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4498 0x00, 0x00, 0x00, 0x04,
4499 0xde, 0xad, 0xbe, 0xef,
4502 SpdyFramer framer(spdy_version_);
4503 TestSpdyVisitor visitor(spdy_version_);
4504 framer.set_visitor(&visitor);
4505 visitor.SimulateInFramer(kInput, sizeof(kInput));
4507 EXPECT_EQ(1, visitor.error_count_);
4508 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4509 visitor.framer_.error_code())
4510 << SpdyFramer::ErrorCodeToString(framer.error_code());
4511 EXPECT_EQ(1, visitor.headers_frame_count_);
4512 EXPECT_EQ(0, visitor.continuation_count_);
4513 EXPECT_EQ(0u, visitor.header_buffer_length_);
4514 EXPECT_EQ(0, visitor.data_frame_count_);
4517 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4518 if (spdy_version_ <= SPDY3) {
4519 return;
4522 const unsigned char kInput[] = {
4523 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4524 0x00, 0x00, 0x00, 0x01, // Stream 1
4525 0x00, 0x06, 0x63, 0x6f,
4526 0x6f, 0x6b, 0x69, 0x65,
4527 0x07, 0x66, 0x6f, 0x6f,
4528 0x3d, 0x62, 0x61, 0x72,
4530 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4531 0x00, 0x00, 0x00, 0x01, // Stream 1
4532 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4533 0x6f, 0x6b, 0x69, 0x65,
4534 0x08, 0x62, 0x61, 0x7a,
4535 0x3d, 0x62, 0x69, 0x6e,
4536 0x67, 0x00, 0x06, 0x63,
4539 SpdyFramer framer(spdy_version_);
4540 TestSpdyVisitor visitor(spdy_version_);
4541 framer.set_visitor(&visitor);
4542 visitor.SimulateInFramer(kInput, sizeof(kInput));
4544 EXPECT_EQ(1, visitor.error_count_);
4545 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4546 visitor.framer_.error_code())
4547 << SpdyFramer::ErrorCodeToString(framer.error_code());
4548 EXPECT_EQ(1, visitor.headers_frame_count_);
4549 EXPECT_EQ(0, visitor.continuation_count_);
4550 EXPECT_EQ(0u, visitor.header_buffer_length_);
4551 EXPECT_EQ(0, visitor.data_frame_count_);
4554 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4555 if (spdy_version_ <= SPDY3) {
4556 return;
4558 const unsigned char kInput[] = {
4559 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4560 0x00, 0x00, 0x00, 0x01, // Stream 1
4561 0xde, 0xad, 0xbe, 0xef,
4562 0xde, 0xad, 0xbe, 0xef,
4563 0xde, 0xad, 0xbe, 0xef,
4566 TestSpdyVisitor visitor(spdy_version_);
4567 visitor.SimulateInFramer(kInput, sizeof(kInput));
4569 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4570 EXPECT_EQ(0, visitor.error_count_);
4571 EXPECT_EQ(12, visitor.data_bytes_);
4572 EXPECT_EQ(0, visitor.fin_frame_count_);
4573 EXPECT_EQ(0, visitor.fin_flag_count_);
4576 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4577 if (spdy_version_ <= SPDY3) {
4578 return;
4580 const unsigned char kInput[] = {
4581 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4582 0x00, 0x00, 0x00, 0x01, // Stream 1
4583 0x00, 0x06, 0x63, 0x6f,
4584 0x6f, 0x6b, 0x69, 0x65,
4585 0x07, 0x66, 0x6f, 0x6f,
4586 0x3d, 0x62, 0x61, 0x72,
4589 TestSpdyVisitor visitor(spdy_version_);
4590 visitor.SimulateInFramer(kInput, sizeof(kInput));
4592 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4593 EXPECT_EQ(0, visitor.error_count_);
4594 EXPECT_EQ(1, visitor.headers_frame_count_);
4595 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4597 EXPECT_THAT(visitor.headers_,
4598 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4601 TEST_P(SpdyFramerTest, ReadGarbage) {
4602 SpdyFramer framer(spdy_version_);
4603 unsigned char garbage_frame[256];
4604 memset(garbage_frame, ~0, sizeof(garbage_frame));
4605 TestSpdyVisitor visitor(spdy_version_);
4606 visitor.use_compression_ = false;
4607 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4608 EXPECT_EQ(1, visitor.error_count_);
4611 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4612 if (spdy_version_ <= SPDY3) {
4613 return;
4615 SpdyFramer framer(spdy_version_);
4617 // The unrecognized frame type should still have a valid length.
4618 const unsigned char unknown_frame[] = {
4619 0x00, 0x00, 0x08, 0xff, 0xff,
4620 0xff, 0xff, 0xff, 0xff,
4621 0xff, 0xff, 0xff, 0xff,
4622 0xff, 0xff, 0xff, 0xff,
4624 TestSpdyVisitor visitor(spdy_version_);
4626 // Simulate the case where the stream id validation checks out.
4627 visitor.on_unknown_frame_result_ = true;
4628 visitor.use_compression_ = false;
4629 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4630 EXPECT_EQ(0, visitor.error_count_);
4632 // Follow it up with a valid control frame to make sure we handle
4633 // subsequent frames correctly.
4634 SpdySettingsIR settings_ir;
4635 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4636 false, // persist
4637 false, // persisted
4638 10);
4639 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4640 visitor.SimulateInFramer(
4641 reinterpret_cast<unsigned char*>(control_frame->data()),
4642 control_frame->size());
4643 EXPECT_EQ(0, visitor.error_count_);
4644 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4645 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4648 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4649 if (!IsSpdy4()) {
4650 return;
4652 SpdyFramer framer(spdy_version_);
4653 const unsigned char kFrameData[] = {
4654 0x00, 0x00, 0x08, 0xff, 0xff,
4655 0xff, 0xff, 0xff, 0xff,
4656 0xff, 0xff, 0xff, 0xff,
4657 0xff, 0xff, 0xff, 0xff,
4659 TestSpdyVisitor visitor(spdy_version_);
4660 visitor.use_compression_ = false;
4661 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4662 EXPECT_EQ(1, visitor.error_count_);
4665 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4666 if (IsSpdy4()) {
4667 // Not valid for SPDY 4 since there is no version field.
4668 return;
4670 SpdyFramer framer(spdy_version_);
4671 const unsigned char kFrameData[] = {
4672 0x80, spdy_version_ch_, 0xff, 0xff,
4673 0xff, 0xff, 0xff, 0xff,
4675 TestSpdyVisitor visitor(spdy_version_);
4676 visitor.use_compression_ = false;
4677 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4678 EXPECT_EQ(1, visitor.error_count_);
4681 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4682 if (spdy_version_ <= SPDY3) {
4683 return;
4685 const unsigned char kInput[] = {
4686 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4687 0x00, 0x00, 0x00, 0x01, // Stream 1
4688 0xef, 0xef, 0xff, 0xff,
4689 0xff, 0xff, 0xff, 0xff,
4690 0xff, 0xff, 0xff, 0xff,
4691 0xff, 0xff, 0xff, 0xff,
4692 0xff, 0xff,
4695 TestSpdyVisitor visitor(spdy_version_);
4696 visitor.SimulateInFramer(kInput, arraysize(kInput));
4697 EXPECT_EQ(1, visitor.error_count_);
4700 TEST_P(SpdyFramerTest, SizesTest) {
4701 SpdyFramer framer(spdy_version_);
4702 if (IsSpdy4()) {
4703 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4704 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4705 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4706 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4707 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4708 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4709 EXPECT_EQ(17u, framer.GetPingSize());
4710 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4711 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4712 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4713 EXPECT_EQ(9u, framer.GetBlockedSize());
4714 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4715 EXPECT_EQ(18u, framer.GetAltSvcMinimumSize());
4716 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4717 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4718 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4719 } else {
4720 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4721 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4722 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4723 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4724 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4725 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4726 EXPECT_EQ(12u, framer.GetPingSize());
4727 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4728 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4729 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4730 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4731 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4732 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4736 TEST_P(SpdyFramerTest, StateToStringTest) {
4737 EXPECT_STREQ("ERROR",
4738 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4739 EXPECT_STREQ("AUTO_RESET",
4740 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4741 EXPECT_STREQ("RESET",
4742 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4743 EXPECT_STREQ("READING_COMMON_HEADER",
4744 SpdyFramer::StateToString(
4745 SpdyFramer::SPDY_READING_COMMON_HEADER));
4746 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4747 SpdyFramer::StateToString(
4748 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4749 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4750 SpdyFramer::StateToString(
4751 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4752 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4753 SpdyFramer::StateToString(
4754 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4755 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4756 SpdyFramer::StateToString(
4757 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4758 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4759 SpdyFramer::StateToString(
4760 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4761 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4762 SpdyFramer::StateToString(
4763 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4764 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4765 SpdyFramer::StateToString(
4766 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4767 EXPECT_STREQ("UNKNOWN_STATE",
4768 SpdyFramer::StateToString(
4769 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4772 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4773 EXPECT_STREQ("NO_ERROR",
4774 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4775 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4776 SpdyFramer::ErrorCodeToString(
4777 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4778 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4779 SpdyFramer::ErrorCodeToString(
4780 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4781 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4782 SpdyFramer::ErrorCodeToString(
4783 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4784 EXPECT_STREQ("UNSUPPORTED_VERSION",
4785 SpdyFramer::ErrorCodeToString(
4786 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4787 EXPECT_STREQ("DECOMPRESS_FAILURE",
4788 SpdyFramer::ErrorCodeToString(
4789 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4790 EXPECT_STREQ("COMPRESS_FAILURE",
4791 SpdyFramer::ErrorCodeToString(
4792 SpdyFramer::SPDY_COMPRESS_FAILURE));
4793 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4794 SpdyFramer::ErrorCodeToString(
4795 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4796 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4797 SpdyFramer::ErrorCodeToString(
4798 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4799 EXPECT_STREQ("UNKNOWN_ERROR",
4800 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4803 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4804 EXPECT_STREQ("INVALID",
4805 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4806 EXPECT_STREQ("PROTOCOL_ERROR",
4807 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4808 EXPECT_STREQ("INVALID_STREAM",
4809 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4810 EXPECT_STREQ("REFUSED_STREAM",
4811 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4812 EXPECT_STREQ("UNSUPPORTED_VERSION",
4813 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4814 EXPECT_STREQ("CANCEL",
4815 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4816 EXPECT_STREQ("INTERNAL_ERROR",
4817 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4818 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4819 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4820 EXPECT_STREQ("UNKNOWN_STATUS",
4821 SpdyFramer::StatusCodeToString(-1));
4824 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4825 EXPECT_STREQ("DATA",
4826 SpdyFramer::FrameTypeToString(DATA));
4827 EXPECT_STREQ("SYN_STREAM",
4828 SpdyFramer::FrameTypeToString(SYN_STREAM));
4829 EXPECT_STREQ("SYN_REPLY",
4830 SpdyFramer::FrameTypeToString(SYN_REPLY));
4831 EXPECT_STREQ("RST_STREAM",
4832 SpdyFramer::FrameTypeToString(RST_STREAM));
4833 EXPECT_STREQ("SETTINGS",
4834 SpdyFramer::FrameTypeToString(SETTINGS));
4835 EXPECT_STREQ("PING",
4836 SpdyFramer::FrameTypeToString(PING));
4837 EXPECT_STREQ("GOAWAY",
4838 SpdyFramer::FrameTypeToString(GOAWAY));
4839 EXPECT_STREQ("HEADERS",
4840 SpdyFramer::FrameTypeToString(HEADERS));
4841 EXPECT_STREQ("WINDOW_UPDATE",
4842 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4843 EXPECT_STREQ("PUSH_PROMISE",
4844 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4845 EXPECT_STREQ("CREDENTIAL",
4846 SpdyFramer::FrameTypeToString(CREDENTIAL));
4847 EXPECT_STREQ("CONTINUATION",
4848 SpdyFramer::FrameTypeToString(CONTINUATION));
4851 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4852 if (IsSpdy4()) {
4853 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4854 return;
4857 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4858 SpdyFramer framer(spdy_version_);
4859 framer.set_visitor(&visitor);
4861 EXPECT_CALL(visitor, OnError(_));
4862 framer.ProcessInput("HTTP/1.1", 8);
4863 EXPECT_TRUE(framer.probable_http_response());
4864 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4865 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4866 << SpdyFramer::ErrorCodeToString(framer.error_code());
4869 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4870 SpdyFramer framer(spdy_version_);
4871 framer.set_visitor(&visitor);
4873 EXPECT_CALL(visitor, OnError(_));
4874 framer.ProcessInput("HTTP/1.0", 8);
4875 EXPECT_TRUE(framer.probable_http_response());
4876 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4877 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4878 << SpdyFramer::ErrorCodeToString(framer.error_code());
4882 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4883 if (spdy_version_ > SPDY3) {
4884 return;
4887 uint8 flags = 0;
4888 do {
4889 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4891 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4892 SpdyFramer framer(spdy_version_);
4893 framer.set_visitor(&visitor);
4895 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4896 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4897 SetFrameFlags(frame.get(), flags, spdy_version_);
4899 if (flags & ~DATA_FLAG_FIN) {
4900 EXPECT_CALL(visitor, OnError(_));
4901 } else {
4902 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4903 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4904 if (flags & DATA_FLAG_FIN) {
4905 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4909 framer.ProcessInput(frame->data(), frame->size());
4910 if (flags & ~DATA_FLAG_FIN) {
4911 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4912 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4913 framer.error_code())
4914 << SpdyFramer::ErrorCodeToString(framer.error_code());
4915 } else {
4916 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4917 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4918 << SpdyFramer::ErrorCodeToString(framer.error_code());
4920 } while (++flags != 0);
4923 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4924 if (spdy_version_ <= SPDY3) {
4925 return;
4928 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4929 DATA_FLAG_PADDED;
4931 uint8 flags = 0;
4932 do {
4933 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4935 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4936 SpdyFramer framer(spdy_version_);
4937 framer.set_visitor(&visitor);
4939 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4940 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4941 SetFrameFlags(frame.get(), flags, spdy_version_);
4943 if (flags & ~valid_data_flags) {
4944 EXPECT_CALL(visitor, OnError(_));
4945 } else {
4946 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4947 if (flags & DATA_FLAG_PADDED) {
4948 // The first byte of payload is parsed as padding length.
4949 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
4950 // Expect Error since the frame ends prematurely.
4951 EXPECT_CALL(visitor, OnError(_));
4952 } else {
4953 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4954 if (flags & DATA_FLAG_FIN) {
4955 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4960 framer.ProcessInput(frame->data(), frame->size());
4961 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
4962 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4963 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4964 << SpdyFramer::ErrorCodeToString(framer.error_code());
4965 } else {
4966 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4967 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4968 << SpdyFramer::ErrorCodeToString(framer.error_code());
4970 } while (++flags != 0);
4973 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4974 if (!IsSpdy2() && !IsSpdy3()) {
4975 // SYN_STREAM not supported in SPDY>3
4976 return;
4978 uint8 flags = 0;
4979 do {
4980 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4982 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4983 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4984 SpdyFramer framer(spdy_version_);
4985 framer.set_visitor(&visitor);
4986 framer.set_debug_visitor(&debug_visitor);
4988 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4990 SpdySynStreamIR syn_stream(8);
4991 syn_stream.set_associated_to_stream_id(3);
4992 syn_stream.set_priority(1);
4993 syn_stream.SetHeader("foo", "bar");
4994 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4995 SetFrameFlags(frame.get(), flags, spdy_version_);
4997 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4998 EXPECT_CALL(visitor, OnError(_));
4999 } else {
5000 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
5001 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
5002 flags & CONTROL_FLAG_UNIDIRECTIONAL));
5003 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
5004 .WillRepeatedly(testing::Return(true));
5005 if (flags & DATA_FLAG_FIN) {
5006 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5007 } else {
5008 // Do not close the stream if we are expecting a CONTINUATION frame.
5009 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5013 framer.ProcessInput(frame->data(), frame->size());
5014 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5015 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5016 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5017 framer.error_code())
5018 << SpdyFramer::ErrorCodeToString(framer.error_code());
5019 } else {
5020 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5021 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5022 << SpdyFramer::ErrorCodeToString(framer.error_code());
5024 } while (++flags != 0);
5027 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
5028 if (!IsSpdy2() && !IsSpdy3()) {
5029 // SYN_REPLY not supported in SPDY>3
5030 return;
5032 uint8 flags = 0;
5033 do {
5034 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5036 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5037 SpdyFramer framer(spdy_version_);
5038 framer.set_visitor(&visitor);
5040 SpdySynReplyIR syn_reply(37);
5041 syn_reply.SetHeader("foo", "bar");
5042 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5043 SetFrameFlags(frame.get(), flags, spdy_version_);
5045 if (flags & ~CONTROL_FLAG_FIN) {
5046 EXPECT_CALL(visitor, OnError(_));
5047 } else {
5048 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5049 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5050 .WillRepeatedly(testing::Return(true));
5051 if (flags & DATA_FLAG_FIN) {
5052 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5056 framer.ProcessInput(frame->data(), frame->size());
5057 if (flags & ~CONTROL_FLAG_FIN) {
5058 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5059 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5060 framer.error_code())
5061 << SpdyFramer::ErrorCodeToString(framer.error_code());
5062 } else {
5063 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5064 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5065 << SpdyFramer::ErrorCodeToString(framer.error_code());
5067 } while (++flags != 0);
5070 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5071 uint8 flags = 0;
5072 do {
5073 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5075 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5076 SpdyFramer framer(spdy_version_);
5077 framer.set_visitor(&visitor);
5079 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5080 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5081 SetFrameFlags(frame.get(), flags, spdy_version_);
5083 if (flags != 0) {
5084 EXPECT_CALL(visitor, OnError(_));
5085 } else {
5086 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5089 framer.ProcessInput(frame->data(), frame->size());
5090 if (flags != 0) {
5091 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5092 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5093 framer.error_code())
5094 << SpdyFramer::ErrorCodeToString(framer.error_code());
5095 } else {
5096 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5097 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5098 << SpdyFramer::ErrorCodeToString(framer.error_code());
5100 } while (++flags != 0);
5103 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5104 if (spdy_version_ > SPDY3) { return; }
5105 uint8 flags = 0;
5106 do {
5107 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5109 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5110 SpdyFramer framer(spdy_version_);
5111 framer.set_visitor(&visitor);
5113 SpdySettingsIR settings_ir;
5114 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5115 false,
5116 false,
5117 54321);
5118 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5119 SetFrameFlags(frame.get(), flags, spdy_version_);
5121 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5122 EXPECT_CALL(visitor, OnError(_));
5123 } else {
5124 EXPECT_CALL(visitor, OnSettings(
5125 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5126 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5127 SETTINGS_FLAG_NONE, 54321));
5128 EXPECT_CALL(visitor, OnSettingsEnd());
5131 framer.ProcessInput(frame->data(), frame->size());
5132 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5133 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5134 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5135 framer.error_code())
5136 << SpdyFramer::ErrorCodeToString(framer.error_code());
5137 } else {
5138 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5139 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5140 << SpdyFramer::ErrorCodeToString(framer.error_code());
5142 } while (++flags != 0);
5145 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5146 if (spdy_version_ <= SPDY3) { return; }
5147 uint8 flags = 0;
5148 do {
5149 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5151 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5152 SpdyFramer framer(spdy_version_);
5153 framer.set_visitor(&visitor);
5155 SpdySettingsIR settings_ir;
5156 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5157 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5158 SetFrameFlags(frame.get(), flags, spdy_version_);
5160 if (flags != 0) {
5161 EXPECT_CALL(visitor, OnError(_));
5162 } else {
5163 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5164 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5165 EXPECT_CALL(visitor, OnSettingsEnd());
5168 framer.ProcessInput(frame->data(), frame->size());
5169 if (flags & ~SETTINGS_FLAG_ACK) {
5170 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5171 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5172 framer.error_code())
5173 << SpdyFramer::ErrorCodeToString(framer.error_code());
5174 } else if (flags & SETTINGS_FLAG_ACK) {
5175 // The frame is invalid because ACK frames should have no payload.
5176 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5177 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5178 framer.error_code())
5179 << SpdyFramer::ErrorCodeToString(framer.error_code());
5180 } else {
5181 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5182 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5183 << SpdyFramer::ErrorCodeToString(framer.error_code());
5185 } while (++flags != 0);
5188 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5189 uint8 flags = 0;
5190 do {
5191 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5193 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5194 SpdyFramer framer(spdy_version_);
5195 framer.set_visitor(&visitor);
5197 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5198 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5199 SetFrameFlags(frame.get(), flags, spdy_version_);
5201 if (flags != 0) {
5202 EXPECT_CALL(visitor, OnError(_));
5203 } else {
5204 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5207 framer.ProcessInput(frame->data(), frame->size());
5208 if (flags != 0) {
5209 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5210 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5211 framer.error_code())
5212 << SpdyFramer::ErrorCodeToString(framer.error_code());
5213 } else {
5214 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5215 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5216 << SpdyFramer::ErrorCodeToString(framer.error_code());
5218 } while (++flags != 0);
5221 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5222 uint8 flags = 0;
5223 do {
5224 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5226 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5227 SpdyFramer framer(spdy_version_);
5228 framer.set_visitor(&visitor);
5230 SpdyHeadersIR headers_ir(57);
5231 if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
5232 headers_ir.set_priority(3);
5233 headers_ir.set_has_priority(true);
5235 headers_ir.SetHeader("foo", "bar");
5236 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5237 uint8 set_flags = flags;
5238 if (IsSpdy4()) {
5239 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5240 // and implement framing.
5241 set_flags &= ~HEADERS_FLAG_PADDED;
5243 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5245 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5246 EXPECT_CALL(visitor, OnError(_));
5247 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5248 HEADERS_FLAG_END_HEADERS |
5249 HEADERS_FLAG_END_SEGMENT |
5250 HEADERS_FLAG_PADDED |
5251 HEADERS_FLAG_PRIORITY)) {
5252 EXPECT_CALL(visitor, OnError(_));
5253 } else {
5254 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5255 EXPECT_CALL(visitor, OnHeaders(57, // stream id
5256 true, // has priority?
5257 3, // priority
5258 flags & CONTROL_FLAG_FIN, // fin?
5259 (flags & HEADERS_FLAG_END_HEADERS) ||
5260 !IsSpdy4())); // end headers?
5261 } else {
5262 EXPECT_CALL(visitor, OnHeaders(57, false, 0,
5263 flags & CONTROL_FLAG_FIN,
5264 (flags & HEADERS_FLAG_END_HEADERS) ||
5265 !IsSpdy4()));
5267 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5268 .WillRepeatedly(testing::Return(true));
5269 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
5270 flags & HEADERS_FLAG_END_HEADERS)) {
5271 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5272 } else {
5273 // Do not close the stream if we are expecting a CONTINUATION frame.
5274 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5278 framer.ProcessInput(frame->data(), frame->size());
5279 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5280 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5281 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5282 framer.error_code())
5283 << SpdyFramer::ErrorCodeToString(framer.error_code());
5284 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5285 HEADERS_FLAG_END_HEADERS |
5286 HEADERS_FLAG_END_SEGMENT |
5287 HEADERS_FLAG_PADDED |
5288 HEADERS_FLAG_PRIORITY)) {
5289 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5290 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5291 framer.error_code())
5292 << SpdyFramer::ErrorCodeToString(framer.error_code());
5293 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5294 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5295 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5296 << SpdyFramer::ErrorCodeToString(framer.error_code());
5297 } else {
5298 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5299 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5300 << SpdyFramer::ErrorCodeToString(framer.error_code());
5302 } while (++flags != 0);
5305 TEST_P(SpdyFramerTest, PingFrameFlags) {
5306 uint8 flags = 0;
5307 do {
5308 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5310 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5311 SpdyFramer framer(spdy_version_);
5312 framer.set_visitor(&visitor);
5314 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5315 SetFrameFlags(frame.get(), flags, spdy_version_);
5317 if (spdy_version_ > SPDY3 &&
5318 flags == PING_FLAG_ACK) {
5319 EXPECT_CALL(visitor, OnPing(42, true));
5320 } else if (flags == 0) {
5321 EXPECT_CALL(visitor, OnPing(42, false));
5322 } else {
5323 EXPECT_CALL(visitor, OnError(_));
5326 framer.ProcessInput(frame->data(), frame->size());
5327 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5328 flags == 0) {
5329 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5330 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5331 << SpdyFramer::ErrorCodeToString(framer.error_code());
5332 } else {
5333 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5334 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5335 framer.error_code())
5336 << SpdyFramer::ErrorCodeToString(framer.error_code());
5338 } while (++flags != 0);
5341 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5342 uint8 flags = 0;
5343 do {
5344 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5346 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5347 SpdyFramer framer(spdy_version_);
5348 framer.set_visitor(&visitor);
5350 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5351 SpdyWindowUpdateIR(4, 1024)));
5352 SetFrameFlags(frame.get(), flags, spdy_version_);
5354 if (flags != 0) {
5355 EXPECT_CALL(visitor, OnError(_));
5356 } else {
5357 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5360 framer.ProcessInput(frame->data(), frame->size());
5361 if (flags != 0) {
5362 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5363 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5364 framer.error_code())
5365 << SpdyFramer::ErrorCodeToString(framer.error_code());
5366 } else {
5367 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5368 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5369 << SpdyFramer::ErrorCodeToString(framer.error_code());
5371 } while (++flags != 0);
5374 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5375 if (spdy_version_ <= SPDY3) {
5376 return;
5379 uint8 flags = 0;
5380 do {
5381 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5383 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
5384 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5385 SpdyFramer framer(spdy_version_);
5386 framer.set_visitor(&visitor);
5387 framer.set_debug_visitor(&debug_visitor);
5389 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5391 SpdyPushPromiseIR push_promise(42, 57);
5392 push_promise.SetHeader("foo", "bar");
5393 scoped_ptr<SpdySerializedFrame> frame(
5394 framer.SerializePushPromise(push_promise));
5395 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5396 // and implement framing.
5397 SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
5399 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5400 EXPECT_CALL(visitor, OnError(_));
5401 } else {
5402 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5403 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5404 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5405 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5406 .WillRepeatedly(testing::Return(true));
5409 framer.ProcessInput(frame->data(), frame->size());
5410 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5411 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5412 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5413 framer.error_code())
5414 << SpdyFramer::ErrorCodeToString(framer.error_code());
5415 } else {
5416 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5417 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5418 << SpdyFramer::ErrorCodeToString(framer.error_code());
5420 } while (++flags != 0);
5423 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5424 if (spdy_version_ <= SPDY3) {
5425 return;
5428 uint8 flags = 0;
5429 do {
5430 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5432 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5433 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5434 SpdyFramer framer(spdy_version_);
5435 framer.set_visitor(&visitor);
5436 framer.set_debug_visitor(&debug_visitor);
5438 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5439 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5440 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false));
5441 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5442 .WillRepeatedly(testing::Return(true));
5444 SpdyHeadersIR headers_ir(42);
5445 headers_ir.SetHeader("foo", "bar");
5446 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5447 SetFrameFlags(frame0.get(), 0, spdy_version_);
5449 SpdyContinuationIR continuation(42);
5450 continuation.SetHeader("foo", "bar");
5451 scoped_ptr<SpdySerializedFrame> frame(
5452 framer.SerializeContinuation(continuation));
5453 SetFrameFlags(frame.get(), flags, spdy_version_);
5455 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5456 EXPECT_CALL(visitor, OnError(_));
5457 } else {
5458 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5459 EXPECT_CALL(visitor, OnContinuation(42,
5460 flags & HEADERS_FLAG_END_HEADERS));
5461 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5462 .WillRepeatedly(testing::Return(true));
5465 framer.ProcessInput(frame0->data(), frame0->size());
5466 framer.ProcessInput(frame->data(), frame->size());
5467 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5468 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5469 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5470 framer.error_code())
5471 << SpdyFramer::ErrorCodeToString(framer.error_code());
5472 } else {
5473 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5474 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5475 << SpdyFramer::ErrorCodeToString(framer.error_code());
5477 } while (++flags != 0);
5480 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5482 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5484 TEST_P(SpdyFramerTest, EmptySynStream) {
5485 if (!IsSpdy2() && !IsSpdy3()) {
5486 // SYN_STREAM not supported in SPDY>3.
5487 return;
5489 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5490 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5491 SpdyFramer framer(spdy_version_);
5492 framer.set_visitor(&visitor);
5493 framer.set_debug_visitor(&debug_visitor);
5495 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5497 SpdySynStreamIR syn_stream(1);
5498 syn_stream.set_priority(1);
5499 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5500 // Adjust size to remove the name/value block.
5501 SetFrameLength(
5502 frame.get(),
5503 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5504 spdy_version_);
5506 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5507 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5508 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5510 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5511 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5512 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5513 << SpdyFramer::ErrorCodeToString(framer.error_code());
5516 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5517 const uint32 kId = 0x020304;
5518 const uint32 kFlags = 0x01;
5519 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5521 SettingsFlagsAndId id_and_flags =
5522 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5523 EXPECT_EQ(kId, id_and_flags.id());
5524 EXPECT_EQ(kFlags, id_and_flags.flags());
5525 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5528 // Test handling of a RST_STREAM with out-of-bounds status codes.
5529 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5530 const unsigned char kRstStreamStatusTooLow = 0x00;
5531 const unsigned char kRstStreamStatusTooHigh = 0xff;
5532 const unsigned char kV3RstStreamInvalid[] = {
5533 0x80, spdy_version_ch_, 0x00, 0x03,
5534 0x00, 0x00, 0x00, 0x08,
5535 0x00, 0x00, 0x00, 0x01,
5536 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5538 const unsigned char kV4RstStreamInvalid[] = {
5539 0x00, 0x00, 0x04, 0x03,
5540 0x00, 0x00, 0x00, 0x00,
5541 0x01, 0x00, 0x00, 0x00,
5542 kRstStreamStatusTooLow
5545 const unsigned char kV3RstStreamNumStatusCodes[] = {
5546 0x80, spdy_version_ch_, 0x00, 0x03,
5547 0x00, 0x00, 0x00, 0x08,
5548 0x00, 0x00, 0x00, 0x01,
5549 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5551 const unsigned char kV4RstStreamNumStatusCodes[] = {
5552 0x00, 0x00, 0x04, 0x03,
5553 0x00, 0x00, 0x00, 0x00,
5554 0x01, 0x00, 0x00, 0x00,
5555 kRstStreamStatusTooHigh
5558 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5559 SpdyFramer framer(spdy_version_);
5560 framer.set_visitor(&visitor);
5562 if (IsSpdy4()) {
5563 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5564 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
5565 arraysize(kV4RstStreamInvalid));
5566 } else {
5567 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5568 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5569 arraysize(kV3RstStreamInvalid));
5571 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5572 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5573 << SpdyFramer::ErrorCodeToString(framer.error_code());
5576 framer.Reset();
5578 if (IsSpdy4()) {
5579 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5580 framer.ProcessInput(
5581 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
5582 arraysize(kV4RstStreamNumStatusCodes));
5583 } else {
5584 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5585 framer.ProcessInput(
5586 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5587 arraysize(kV3RstStreamNumStatusCodes));
5589 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5590 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5591 << SpdyFramer::ErrorCodeToString(framer.error_code());
5594 // Test handling of GOAWAY frames with out-of-bounds status code.
5595 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5596 if (spdy_version_ <= SPDY2) {
5597 return;
5599 SpdyFramer framer(spdy_version_);
5601 const unsigned char kV3FrameData[] = {
5602 0x80, spdy_version_ch_, 0x00, 0x07,
5603 0x00, 0x00, 0x00, 0x08,
5604 0x00, 0x00, 0x00, 0x01, // Stream Id
5605 0xff, 0xff, 0xff, 0xff, // Status
5607 const unsigned char kV4FrameData[] = {
5608 0x00, 0x00, 0x0a, 0x07,
5609 0x00, 0x00, 0x00, 0x00,
5610 0x00, 0x00, 0x00, 0x00, // Stream id
5611 0x01, 0xff, 0xff, 0xff, // Status
5612 0xff, 0x47, 0x41, // Opaque Description
5614 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5615 framer.set_visitor(&visitor);
5617 if (IsSpdy3()) {
5618 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5619 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5620 arraysize(kV3FrameData));
5621 } else {
5622 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5623 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5624 arraysize(kV4FrameData));
5626 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5627 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5628 << SpdyFramer::ErrorCodeToString(framer.error_code());
5631 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5632 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5633 const unsigned char kV2FrameData[] = {
5634 0x80, spdy_version_ch_, 0x00, 0x07,
5635 0x00, 0x00, 0x00, 0x04,
5636 0xff, 0xff, 0xff, 0xff,
5638 const unsigned char kV3FrameData[] = {
5639 0x80, spdy_version_ch_, 0x00, 0x07,
5640 0x00, 0x00, 0x00, 0x08,
5641 0xff, 0xff, 0xff, 0xff,
5642 0x00, 0x00, 0x00, 0x00,
5644 const unsigned char kV4FrameData[] = {
5645 0x00, 0x00, 0x08, 0x07,
5646 0x00, 0x00, 0x00, 0x00,
5647 0x00, 0xff, 0xff, 0xff,
5648 0xff, 0x00, 0x00, 0x00,
5649 0x00,
5652 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5653 SpdyFramer framer(spdy_version_);
5654 framer.set_visitor(&visitor);
5656 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5657 if (IsSpdy2()) {
5658 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5659 arraysize(kV2FrameData));
5660 } else if (IsSpdy3()) {
5661 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5662 arraysize(kV3FrameData));
5663 } else {
5664 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5665 arraysize(kV4FrameData));
5667 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5668 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5669 << SpdyFramer::ErrorCodeToString(framer.error_code());
5672 TEST_P(SpdyFramerTest, OnBlocked) {
5673 if (spdy_version_ <= SPDY3) {
5674 return;
5677 const SpdyStreamId kStreamId = 0;
5679 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5680 SpdyFramer framer(spdy_version_);
5681 framer.set_visitor(&visitor);
5683 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5685 SpdyBlockedIR blocked_ir(0);
5686 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5687 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5689 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5690 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5691 << SpdyFramer::ErrorCodeToString(framer.error_code());
5694 TEST_P(SpdyFramerTest, OnAltSvc) {
5695 if (spdy_version_ <= SPDY3) {
5696 return;
5699 const SpdyStreamId kStreamId = 1;
5701 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5702 SpdyFramer framer(spdy_version_);
5703 framer.set_visitor(&visitor);
5705 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5707 443,
5708 StringPiece("pid"),
5709 StringPiece("h1"),
5710 StringPiece("o1")));
5712 SpdyAltSvcIR altsvc_ir(1);
5713 altsvc_ir.set_max_age(10);
5714 altsvc_ir.set_port(443);
5715 altsvc_ir.set_protocol_id("pid");
5716 altsvc_ir.set_host("h1");
5717 altsvc_ir.set_origin("o1");
5718 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5719 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5720 altsvc_ir.protocol_id().length() +
5721 altsvc_ir.host().length() +
5722 altsvc_ir.origin().length());
5724 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5725 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5726 << SpdyFramer::ErrorCodeToString(framer.error_code());
5729 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5730 if (spdy_version_ <= SPDY3) {
5731 return;
5734 const SpdyStreamId kStreamId = 1;
5736 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5737 SpdyFramer framer(spdy_version_);
5738 framer.set_visitor(&visitor);
5740 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5742 443,
5743 StringPiece("pid"),
5744 StringPiece("h1"),
5745 StringPiece("")));
5747 SpdyAltSvcIR altsvc_ir(1);
5748 altsvc_ir.set_max_age(10);
5749 altsvc_ir.set_port(443);
5750 altsvc_ir.set_protocol_id("pid");
5751 altsvc_ir.set_host("h1");
5752 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5753 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5754 altsvc_ir.protocol_id().length() +
5755 altsvc_ir.host().length());
5757 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5758 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5759 << SpdyFramer::ErrorCodeToString(framer.error_code());
5762 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5763 if (spdy_version_ <= SPDY3) {
5764 return;
5767 const unsigned char kType = static_cast<unsigned char>(
5768 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
5770 TestSpdyVisitor visitor(spdy_version_);
5771 SpdyFramer framer(spdy_version_);
5772 framer.set_visitor(&visitor);
5774 const unsigned char kFrameDataLargePIDLen[] = {
5775 0x00, 0x00, 0x17, kType, 0x00,
5776 0x00, 0x00, 0x00, 0x03,
5777 0x00, 0x00, 0x00, 0x05,
5778 0x01, 0xbb, 0x00, 0x05, // Port = 443
5779 'p', 'i', 'd', '1', // Protocol-ID
5780 0x04, 'h', 'o', 's',
5781 't', 'o', 'r', 'i',
5782 'g', 'i', 'n',
5785 visitor.SimulateInFramer(kFrameDataLargePIDLen,
5786 sizeof(kFrameDataLargePIDLen));
5787 EXPECT_EQ(1, visitor.error_count_);
5788 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5789 visitor.framer_.error_code());
5793 TestSpdyVisitor visitor(spdy_version_);
5794 SpdyFramer framer(spdy_version_);
5795 framer.set_visitor(&visitor);
5796 const unsigned char kFrameDataPIDLenLargerThanFrame[] = {
5797 0x00, 0x00, 0x17, kType, 0x00,
5798 0x00, 0x00, 0x00, 0x03,
5799 0x00, 0x00, 0x00, 0x05,
5800 0x01, 0xbb, 0x00, 0x99, // Port = 443
5801 'p', 'i', 'd', '1', // Protocol-ID
5802 0x04, 'h', 'o', 's',
5803 't', 'o', 'r', 'i',
5804 'g', 'i', 'n',
5807 visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame,
5808 sizeof(kFrameDataPIDLenLargerThanFrame));
5809 EXPECT_EQ(1, visitor.error_count_);
5810 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5811 visitor.framer_.error_code());
5815 TestSpdyVisitor visitor(spdy_version_);
5816 SpdyFramer framer(spdy_version_);
5817 framer.set_visitor(&visitor);
5819 const unsigned char kFrameDataLargeHostLen[] = {
5820 0x00, 0x00, 0x17, kType, 0x00,
5821 0x00, 0x00, 0x00, 0x03,
5822 0x00, 0x00, 0x00, 0x05,
5823 0x01, 0xbb, 0x00, 0x04, // Port = 443
5824 'p', 'i', 'd', '1', // Protocol-ID
5825 0x0f, 'h', 'o', 's',
5826 't', 'o', 'r', 'i',
5827 'g', 'i', 'n',
5830 visitor.SimulateInFramer(kFrameDataLargeHostLen,
5831 sizeof(kFrameDataLargeHostLen));
5832 EXPECT_EQ(1, visitor.error_count_);
5833 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5834 visitor.framer_.error_code());
5838 TestSpdyVisitor visitor(spdy_version_);
5839 SpdyFramer framer(spdy_version_);
5840 framer.set_visitor(&visitor);
5841 const unsigned char kFrameDataSmallPIDLen[] = {
5842 0x00, 0x00, 0x17, kType, 0x00,
5843 0x00, 0x00, 0x00, 0x03,
5844 0x00, 0x00, 0x00, 0x05,
5845 0x01, 0xbb, 0x00, 0x01, // Port = 443
5846 'p', 'i', 'd', '1', // Protocol-ID
5847 0x04, 'h', 'o', 's',
5848 't', 'o', 'r', 'i',
5849 'g', 'i', 'n',
5852 visitor.SimulateInFramer(kFrameDataSmallPIDLen,
5853 sizeof(kFrameDataSmallPIDLen));
5854 EXPECT_EQ(1, visitor.error_count_);
5855 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5856 visitor.framer_.error_code());
5860 // Tests handling of ALTSVC frames delivered in small chunks.
5861 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5862 if (spdy_version_ <= SPDY3) {
5863 return;
5865 SpdyFramer framer(spdy_version_);
5866 SpdyAltSvcIR altsvc_ir(1);
5867 altsvc_ir.set_max_age(20);
5868 altsvc_ir.set_port(443);
5869 altsvc_ir.set_protocol_id("protocolid");
5870 altsvc_ir.set_host("hostname");
5872 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5873 TestSpdyVisitor visitor(spdy_version_);
5874 visitor.use_compression_ = false;
5876 // Read data in small chunks.
5877 size_t framed_data = 0;
5878 size_t unframed_data = control_frame->size();
5879 size_t kReadChunkSize = 5; // Read five bytes at a time.
5880 while (unframed_data > 0) {
5881 size_t to_read = std::min(kReadChunkSize, unframed_data);
5882 visitor.SimulateInFramer(
5883 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5884 to_read);
5885 unframed_data -= to_read;
5886 framed_data += to_read;
5888 EXPECT_EQ(0, visitor.error_count_);
5889 EXPECT_EQ(1, visitor.altsvc_count_);
5890 EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
5891 EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
5892 EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
5893 EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
5896 // Tests handling of PRIORITY frames.
5897 TEST_P(SpdyFramerTest, ReadPriority) {
5898 if (spdy_version_ <= SPDY3) {
5899 return;
5901 SpdyFramer framer(spdy_version_);
5902 SpdyPriorityIR priority(3, 1, 255, false);
5903 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5904 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5905 framer.set_visitor(&visitor);
5906 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5907 framer.ProcessInput(frame->data(), frame->size());
5909 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5910 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5911 << SpdyFramer::ErrorCodeToString(framer.error_code());
5912 // TODO(mlavan): once we actually maintain a priority tree,
5913 // check that state is adjusted correctly.
5916 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5917 if (spdy_version_ <= SPDY3) {
5918 return;
5920 SpdyFramer framer(spdy_version_);
5922 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5923 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5924 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5925 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5926 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5927 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5928 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5929 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5931 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5932 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5933 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5934 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5935 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5936 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5937 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5938 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5939 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5940 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5941 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5942 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5943 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5944 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5945 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5948 // Tests handling of PRIORITY frame with incorrect size.
5949 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5950 if (spdy_version_ <= SPDY3) {
5951 return;
5954 // PRIORITY frame of size 4, which isn't correct.
5955 const unsigned char kFrameData[] = {
5956 0x00, 0x00, 0x04, 0x02, 0x00,
5957 0x00, 0x00, 0x00, 0x03,
5958 0x00, 0x00, 0x00, 0x01,
5961 TestSpdyVisitor visitor(spdy_version_);
5962 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
5964 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
5965 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5966 visitor.framer_.error_code())
5967 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
5970 } // namespace net