prune resources in MemoryCache
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob2309bda8e0d537fc93f73f1e9feb3dfdb5270014
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 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
93 const char* header_data,
94 size_t len) override {
95 CHECK(buffer_.get() != NULL);
96 CHECK_GE(kMaxDecompressedSize, size_ + len);
97 CHECK(!finished_);
98 if (len != 0) {
99 memcpy(buffer_.get() + size_, header_data, len);
100 size_ += len;
101 } else {
102 // Done.
103 finished_ = true;
105 return true;
108 void OnSynStream(SpdyStreamId stream_id,
109 SpdyStreamId associated_stream_id,
110 SpdyPriority priority,
111 bool fin,
112 bool unidirectional) override {
113 SpdyFramer framer(version_);
114 framer.set_enable_compression(false);
115 SpdySynStreamIR syn_stream(stream_id);
116 syn_stream.set_associated_to_stream_id(associated_stream_id);
117 syn_stream.set_priority(priority);
118 syn_stream.set_fin(fin);
119 syn_stream.set_unidirectional(unidirectional);
120 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
121 ResetBuffer();
122 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
123 size_ += framer.GetSynStreamMinimumSize();
126 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
127 SpdyFramer framer(version_);
128 framer.set_enable_compression(false);
129 SpdyHeadersIR headers(stream_id);
130 headers.set_fin(fin);
131 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
132 ResetBuffer();
133 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
134 size_ += framer.GetSynStreamMinimumSize();
137 void OnRstStream(SpdyStreamId stream_id,
138 SpdyRstStreamStatus status) override {
139 LOG(FATAL);
141 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
142 LOG(FATAL);
144 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
145 void OnSettingsEnd() override { LOG(FATAL); }
146 void OnGoAway(SpdyStreamId last_accepted_stream_id,
147 SpdyGoAwayStatus status) override {
148 LOG(FATAL);
151 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
152 SpdyPriority priority, bool fin, bool end) override {
153 SpdyFramer framer(version_);
154 framer.set_enable_compression(false);
155 SpdyHeadersIR headers(stream_id);
156 headers.set_has_priority(has_priority);
157 if (headers.has_priority()) {
158 headers.set_priority(priority);
160 headers.set_fin(fin);
161 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
162 ResetBuffer();
163 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
164 size_ += framer.GetHeadersMinimumSize();
167 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
168 LOG(FATAL);
171 void OnPushPromise(SpdyStreamId stream_id,
172 SpdyStreamId promised_stream_id,
173 bool end) override {
174 SpdyFramer framer(version_);
175 framer.set_enable_compression(false);
176 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
177 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
178 ResetBuffer();
179 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
180 size_ += framer.GetPushPromiseMinimumSize();
183 void OnContinuation(SpdyStreamId stream_id, bool end) override {
184 LOG(FATAL);
187 void OnPriority(SpdyStreamId stream_id,
188 SpdyStreamId parent_stream_id,
189 uint8 weight,
190 bool exclusive) override {
191 // Do nothing.
194 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
195 LOG(FATAL);
196 return false;
199 char* ReleaseBuffer() {
200 CHECK(finished_);
201 return buffer_.release();
204 void OnWindowUpdate(SpdyStreamId stream_id,
205 uint32 delta_window_size) override {
206 LOG(FATAL);
209 size_t size() const {
210 CHECK(finished_);
211 return size_;
214 private:
215 SpdyMajorVersion version_;
216 scoped_ptr<char[]> buffer_;
217 size_t size_;
218 bool finished_;
220 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
223 private:
224 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
227 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
228 public SpdyFramerDebugVisitorInterface {
229 public:
230 // This is larger than our max frame size because header blocks that
231 // are too long can spill over into CONTINUATION frames.
232 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
234 explicit TestSpdyVisitor(SpdyMajorVersion version)
235 : framer_(version),
236 use_compression_(false),
237 error_count_(0),
238 syn_frame_count_(0),
239 syn_reply_frame_count_(0),
240 headers_frame_count_(0),
241 push_promise_frame_count_(0),
242 goaway_count_(0),
243 setting_count_(0),
244 settings_ack_sent_(0),
245 settings_ack_received_(0),
246 continuation_count_(0),
247 altsvc_count_(0),
248 priority_count_(0),
249 test_altsvc_ir_(0),
250 on_unknown_frame_result_(false),
251 last_window_update_stream_(0),
252 last_window_update_delta_(0),
253 last_push_promise_stream_(0),
254 last_push_promise_promised_stream_(0),
255 data_bytes_(0),
256 fin_frame_count_(0),
257 fin_opaque_data_(),
258 fin_flag_count_(0),
259 zero_length_data_frame_count_(0),
260 control_frame_header_data_count_(0),
261 zero_length_control_frame_header_data_count_(0),
262 data_frame_count_(0),
263 last_payload_len_(0),
264 last_frame_len_(0),
265 header_buffer_(new char[kDefaultHeaderBufferSize]),
266 header_buffer_length_(0),
267 header_buffer_size_(kDefaultHeaderBufferSize),
268 header_stream_id_(static_cast<SpdyStreamId>(-1)),
269 header_control_type_(DATA),
270 header_buffer_valid_(false) {}
272 void OnError(SpdyFramer* f) override {
273 LOG(INFO) << "SpdyFramer Error: "
274 << SpdyFramer::ErrorCodeToString(f->error_code());
275 ++error_count_;
278 void OnDataFrameHeader(SpdyStreamId stream_id,
279 size_t length,
280 bool fin) override {
281 ++data_frame_count_;
282 header_stream_id_ = stream_id;
285 void OnStreamFrameData(SpdyStreamId stream_id,
286 const char* data,
287 size_t len,
288 bool fin) override {
289 EXPECT_EQ(header_stream_id_, stream_id);
290 if (len == 0)
291 ++zero_length_data_frame_count_;
293 data_bytes_ += len;
294 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
295 if (len > 0) {
296 for (size_t i = 0 ; i < len; ++i) {
297 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
300 std::cerr << "\", " << len << ")\n";
303 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
304 const char* header_data,
305 size_t len) override {
306 ++control_frame_header_data_count_;
307 CHECK_EQ(header_stream_id_, stream_id);
308 if (len == 0) {
309 ++zero_length_control_frame_header_data_count_;
310 // Indicates end-of-header-block.
311 headers_.clear();
312 CHECK(header_buffer_valid_);
313 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
314 header_buffer_.get(), header_buffer_length_, &headers_);
315 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
316 << "Check failed: header_buffer_length_ == parsed_length "
317 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
318 return true;
320 const size_t available = header_buffer_size_ - header_buffer_length_;
321 if (len > available) {
322 header_buffer_valid_ = false;
323 return false;
325 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
326 header_buffer_length_ += len;
327 return true;
330 void OnSynStream(SpdyStreamId stream_id,
331 SpdyStreamId associated_stream_id,
332 SpdyPriority priority,
333 bool fin,
334 bool unidirectional) override {
335 ++syn_frame_count_;
336 if (framer_.protocol_version() > SPDY3) {
337 InitHeaderStreaming(HEADERS, stream_id);
338 } else {
339 InitHeaderStreaming(SYN_STREAM, stream_id);
341 if (fin) {
342 ++fin_flag_count_;
346 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
347 ++syn_reply_frame_count_;
348 if (framer_.protocol_version() > SPDY3) {
349 InitHeaderStreaming(HEADERS, stream_id);
350 } else {
351 InitHeaderStreaming(SYN_REPLY, stream_id);
353 if (fin) {
354 ++fin_flag_count_;
358 void OnRstStream(SpdyStreamId stream_id,
359 SpdyRstStreamStatus status) override {
360 ++fin_frame_count_;
363 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
364 if ((rst_stream_data != NULL) && (len > 0)) {
365 fin_opaque_data_ += string(rst_stream_data, len);
367 return true;
370 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
371 ++setting_count_;
374 void OnSettingsAck() override {
375 DCHECK_LT(SPDY3, framer_.protocol_version());
376 ++settings_ack_received_;
379 void OnSettingsEnd() override {
380 if (framer_.protocol_version() <= SPDY3) { return; }
381 ++settings_ack_sent_;
384 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
386 void OnGoAway(SpdyStreamId last_accepted_stream_id,
387 SpdyGoAwayStatus status) override {
388 ++goaway_count_;
391 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
392 SpdyPriority priority, bool fin, bool end) override {
393 ++headers_frame_count_;
394 InitHeaderStreaming(HEADERS, stream_id);
395 if (fin) {
396 ++fin_flag_count_;
400 void OnWindowUpdate(SpdyStreamId stream_id,
401 uint32 delta_window_size) override {
402 last_window_update_stream_ = stream_id;
403 last_window_update_delta_ = delta_window_size;
406 void OnPushPromise(SpdyStreamId stream_id,
407 SpdyStreamId promised_stream_id,
408 bool end) override {
409 ++push_promise_frame_count_;
410 InitHeaderStreaming(PUSH_PROMISE, stream_id);
411 last_push_promise_stream_ = stream_id;
412 last_push_promise_promised_stream_ = promised_stream_id;
415 void OnContinuation(SpdyStreamId stream_id, bool end) override {
416 ++continuation_count_;
419 void OnAltSvc(SpdyStreamId stream_id,
420 uint32 max_age,
421 uint16 port,
422 StringPiece protocol_id,
423 StringPiece host,
424 StringPiece origin) override {
425 test_altsvc_ir_.set_stream_id(stream_id);
426 test_altsvc_ir_.set_max_age(max_age);
427 test_altsvc_ir_.set_port(port);
428 test_altsvc_ir_.set_protocol_id(protocol_id.as_string());
429 test_altsvc_ir_.set_host(host.as_string());
430 if (origin.length() > 0) {
431 test_altsvc_ir_.set_origin(origin.as_string());
433 ++altsvc_count_;
436 void OnPriority(SpdyStreamId stream_id,
437 SpdyStreamId parent_stream_id,
438 uint8 weight,
439 bool exclusive) override {
440 ++priority_count_;
443 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
444 DLOG(INFO) << "Unknown frame type " << frame_type;
445 return on_unknown_frame_result_;
448 void OnSendCompressedFrame(SpdyStreamId stream_id,
449 SpdyFrameType type,
450 size_t payload_len,
451 size_t frame_len) override {
452 last_payload_len_ = payload_len;
453 last_frame_len_ = frame_len;
456 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
457 SpdyFrameType type,
458 size_t frame_len) override {
459 last_frame_len_ = frame_len;
462 // Convenience function which runs a framer simulation with particular input.
463 void SimulateInFramer(const unsigned char* input, size_t size) {
464 framer_.set_enable_compression(use_compression_);
465 framer_.set_visitor(this);
466 size_t input_remaining = size;
467 const char* input_ptr = reinterpret_cast<const char*>(input);
468 while (input_remaining > 0 &&
469 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
470 // To make the tests more interesting, we feed random (amd small) chunks
471 // into the framer. This simulates getting strange-sized reads from
472 // the socket.
473 const size_t kMaxReadSize = 32;
474 size_t bytes_read =
475 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
476 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
477 input_remaining -= bytes_processed;
478 input_ptr += bytes_processed;
482 void InitHeaderStreaming(SpdyFrameType header_control_type,
483 SpdyStreamId stream_id) {
484 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
485 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
486 header_control_type))) {
487 DLOG(FATAL) << "Attempted to init header streaming with "
488 << "invalid control frame type: "
489 << header_control_type;
491 memset(header_buffer_.get(), 0, header_buffer_size_);
492 header_buffer_length_ = 0;
493 header_stream_id_ = stream_id;
494 header_control_type_ = header_control_type;
495 header_buffer_valid_ = true;
496 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
499 // Override the default buffer size (16K). Call before using the framer!
500 void set_header_buffer_size(size_t header_buffer_size) {
501 header_buffer_size_ = header_buffer_size;
502 header_buffer_.reset(new char[header_buffer_size]);
505 // Largest control frame that the SPDY implementation sends, including the
506 // size of the header.
507 static size_t sent_control_frame_max_size() {
508 return SpdyFramer::kMaxControlFrameSize;
511 static size_t header_data_chunk_max_size() {
512 return SpdyFramer::kHeaderDataChunkMaxSize;
515 SpdyFramer framer_;
516 bool use_compression_;
518 // Counters from the visitor callbacks.
519 int error_count_;
520 int syn_frame_count_;
521 int syn_reply_frame_count_;
522 int headers_frame_count_;
523 int push_promise_frame_count_;
524 int goaway_count_;
525 int setting_count_;
526 int settings_ack_sent_;
527 int settings_ack_received_;
528 int continuation_count_;
529 int altsvc_count_;
530 int priority_count_;
531 SpdyAltSvcIR test_altsvc_ir_;
532 bool on_unknown_frame_result_;
533 SpdyStreamId last_window_update_stream_;
534 uint32 last_window_update_delta_;
535 SpdyStreamId last_push_promise_stream_;
536 SpdyStreamId last_push_promise_promised_stream_;
537 int data_bytes_;
538 int fin_frame_count_; // The count of RST_STREAM type frames received.
539 string fin_opaque_data_;
540 int fin_flag_count_; // The count of frames with the FIN flag set.
541 int zero_length_data_frame_count_; // The count of zero-length data frames.
542 int control_frame_header_data_count_; // The count of chunks received.
543 // The count of zero-length control frame header data chunks received.
544 int zero_length_control_frame_header_data_count_;
545 int data_frame_count_;
546 size_t last_payload_len_;
547 size_t last_frame_len_;
549 // Header block streaming state:
550 scoped_ptr<char[]> header_buffer_;
551 size_t header_buffer_length_;
552 size_t header_buffer_size_;
553 SpdyStreamId header_stream_id_;
554 SpdyFrameType header_control_type_;
555 bool header_buffer_valid_;
556 SpdyHeaderBlock headers_;
559 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
560 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
561 const SpdyFramer& framer) {
562 SpdyFrameReader reader(frame->data(), frame->size());
563 if (framer.protocol_version() > SPDY3) {
564 reader.Seek(3); // Seek past the frame length.
565 } else {
566 reader.Seek(2); // Seek past the frame length.
568 SpdyFrameType frame_type;
569 if (framer.protocol_version() > SPDY3) {
570 uint8 serialized_type;
571 reader.ReadUInt8(&serialized_type);
572 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
573 serialized_type);
574 DCHECK_EQ(HEADERS, frame_type);
575 uint8 flags;
576 reader.ReadUInt8(&flags);
577 if (flags & HEADERS_FLAG_PRIORITY) {
578 frame_type = SYN_STREAM;
580 } else {
581 uint16 serialized_type;
582 reader.ReadUInt16(&serialized_type);
583 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
584 serialized_type);
585 DCHECK(frame_type == HEADERS ||
586 frame_type == SYN_STREAM) << frame_type;
589 if (frame_type == SYN_STREAM) {
590 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
591 frame->size() - framer.GetSynStreamMinimumSize());
592 } else {
593 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
594 frame->size() - framer.GetHeadersMinimumSize());
598 } // namespace test
600 } // namespace net
602 using net::test::SetFrameLength;
603 using net::test::SetFrameFlags;
604 using net::test::CompareCharArraysWithHexError;
605 using net::test::SpdyFramerTestUtil;
606 using net::test::TestSpdyVisitor;
607 using net::test::GetSerializedHeaders;
609 namespace net {
611 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
612 protected:
613 void SetUp() override {
614 spdy_version_ = GetParam();
615 spdy_version_ch_ = static_cast<unsigned char>(
616 SpdyConstants::SerializeMajorVersion(spdy_version_));
619 void CompareFrame(const string& description,
620 const SpdyFrame& actual_frame,
621 const unsigned char* expected,
622 const int expected_len) {
623 const unsigned char* actual =
624 reinterpret_cast<const unsigned char*>(actual_frame.data());
625 CompareCharArraysWithHexError(
626 description, actual, actual_frame.size(), expected, expected_len);
629 void CompareFrames(const string& description,
630 const SpdyFrame& expected_frame,
631 const SpdyFrame& actual_frame) {
632 CompareCharArraysWithHexError(
633 description,
634 reinterpret_cast<const unsigned char*>(expected_frame.data()),
635 expected_frame.size(),
636 reinterpret_cast<const unsigned char*>(actual_frame.data()),
637 actual_frame.size());
640 // Returns true if the two header blocks have equivalent content.
641 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
642 const SpdyHeaderBlock* actual) {
643 if (expected->size() != actual->size()) {
644 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
645 << actual->size() << ".";
646 return false;
648 for (SpdyHeaderBlock::const_iterator it = expected->begin();
649 it != expected->end();
650 ++it) {
651 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
652 if (it2 == actual->end()) {
653 LOG(ERROR) << "Expected header name '" << it->first << "'.";
654 return false;
656 if (it->second.compare(it2->second) != 0) {
657 LOG(ERROR) << "Expected header named '" << it->first
658 << "' to have a value of '" << it->second
659 << "'. The actual value received was '" << it2->second
660 << "'.";
661 return false;
664 return true;
667 bool IsSpdy2() { return spdy_version_ == SPDY2; }
668 bool IsSpdy3() { return spdy_version_ == SPDY3; }
669 bool IsSpdy4() { return spdy_version_ == SPDY4; }
670 bool IsSpdy5() { return spdy_version_ == SPDY5; }
672 // Version of SPDY protocol to be used.
673 SpdyMajorVersion spdy_version_;
674 unsigned char spdy_version_ch_;
677 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
678 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
679 SpdyFramerTest,
680 ::testing::Values(SPDY2, SPDY3, SPDY4));
682 // Test that we ignore cookie where both name and value are empty.
683 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
684 if (spdy_version_ > SPDY3) {
685 // Not implemented for hpack.
686 return;
689 SpdyFramer framer(spdy_version_);
690 framer.set_enable_compression(true);
691 SpdyHeadersIR headers(1);
692 headers.set_priority(1);
693 headers.SetHeader("cookie",
694 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
695 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
696 EXPECT_TRUE(frame.get() != NULL);
698 TestSpdyVisitor visitor(spdy_version_);
699 visitor.use_compression_ = true;
700 visitor.SimulateInFramer(
701 reinterpret_cast<unsigned char*>(frame->data()),
702 frame->size());
704 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
705 EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
706 &visitor.headers_));
707 EXPECT_EQ(1u, visitor.headers_.size());
708 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
711 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
712 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
713 SpdyFramer framer(spdy_version_);
714 framer.set_enable_compression(false);
716 // Encode the header block into a Headers frame.
717 SpdyHeadersIR headers(1);
718 headers.set_priority(1);
719 headers.SetHeader("alpha", "beta");
720 headers.SetHeader("gamma", "charlie");
721 headers.SetHeader("cookie", "key1=value1; key2=value2");
722 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
723 EXPECT_TRUE(frame.get() != NULL);
725 TestSpdyVisitor visitor(spdy_version_);
726 visitor.use_compression_ = false;
727 visitor.SimulateInFramer(
728 reinterpret_cast<unsigned char*>(frame->data()),
729 frame->size());
731 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
732 EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
733 &visitor.headers_));
736 // Test that if there's not a full frame, we fail to parse it.
737 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
738 SpdyFramer framer(spdy_version_);
739 framer.set_enable_compression(false);
741 // Encode the header block into a Headers frame.
742 SpdyHeadersIR headers(1);
743 headers.set_priority(1);
744 headers.SetHeader("alpha", "beta");
745 headers.SetHeader("gamma", "charlie");
746 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
747 EXPECT_TRUE(frame.get() != NULL);
749 TestSpdyVisitor visitor(spdy_version_);
750 visitor.use_compression_ = false;
751 visitor.SimulateInFramer(
752 reinterpret_cast<unsigned char*>(frame->data()),
753 frame->size() - 2);
755 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
756 EXPECT_EQ(0u, visitor.headers_.size());
759 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
760 // (but don't crash).
761 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
762 if (spdy_version_ > SPDY3) {
763 return;
765 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
766 SpdyFramer framer(spdy_version_);
767 framer.set_visitor(&visitor);
769 SpdySynReplyIR syn_reply(0);
770 syn_reply.SetHeader("alpha", "beta");
771 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
772 ASSERT_TRUE(frame.get() != NULL);
774 // We shouldn't have to read the whole frame before we signal an error.
775 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
776 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
777 EXPECT_TRUE(framer.HasError());
778 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
779 << SpdyFramer::ErrorCodeToString(framer.error_code());
782 // Test that if we receive a HEADERS with stream ID zero, we signal an error
783 // (but don't crash).
784 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
785 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
786 SpdyFramer framer(spdy_version_);
787 framer.set_visitor(&visitor);
789 SpdyHeadersIR headers_ir(0);
790 headers_ir.SetHeader("alpha", "beta");
791 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
792 ASSERT_TRUE(frame.get() != NULL);
794 // We shouldn't have to read the whole frame before we signal an error.
795 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
796 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
797 EXPECT_TRUE(framer.HasError());
798 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
799 << SpdyFramer::ErrorCodeToString(framer.error_code());
802 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
803 // error (but don't crash).
804 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
805 if (spdy_version_ <= SPDY3) {
806 return;
809 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
810 SpdyFramer framer(spdy_version_);
811 framer.set_visitor(&visitor);
813 SpdyPushPromiseIR push_promise(0, 4);
814 push_promise.SetHeader("alpha", "beta");
815 scoped_ptr<SpdySerializedFrame> frame(
816 framer.SerializePushPromise(push_promise));
817 ASSERT_TRUE(frame.get() != NULL);
819 // We shouldn't have to read the whole frame before we signal an error.
820 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
821 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
822 EXPECT_TRUE(framer.HasError());
823 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
824 << SpdyFramer::ErrorCodeToString(framer.error_code());
827 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
828 // signal an error (but don't crash).
829 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
830 if (spdy_version_ <= SPDY3) {
831 return;
834 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
835 SpdyFramer framer(spdy_version_);
836 framer.set_visitor(&visitor);
838 SpdyPushPromiseIR push_promise(3, 0);
839 push_promise.SetHeader("alpha", "beta");
840 scoped_ptr<SpdySerializedFrame> frame(
841 framer.SerializePushPromise(push_promise));
842 ASSERT_TRUE(frame.get() != NULL);
844 // We shouldn't have to read the whole frame before we signal an error.
845 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
846 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
847 EXPECT_TRUE(framer.HasError());
848 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
849 << SpdyFramer::ErrorCodeToString(framer.error_code());
852 TEST_P(SpdyFramerTest, DuplicateHeader) {
853 if (spdy_version_ > SPDY3) {
854 // TODO(jgraettinger): Punting on this because we haven't determined
855 // whether duplicate HPACK headers other than Cookie are an error.
856 // If they are, this will need to be updated to use HpackOutputStream.
857 return;
859 SpdyFramer framer(spdy_version_);
860 // Frame builder with plentiful buffer size.
861 SpdyFrameBuilder frame(1024, spdy_version_);
862 if (spdy_version_ <= SPDY3) {
863 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
864 frame.WriteUInt32(3); // stream_id
865 frame.WriteUInt32(0); // associated stream id
866 frame.WriteUInt16(0); // Priority.
867 } else {
868 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
869 frame.WriteUInt32(framer.GetHighestPriority());
872 if (IsSpdy2()) {
873 frame.WriteUInt16(2); // Number of headers.
874 frame.WriteString("name");
875 frame.WriteString("value1");
876 frame.WriteString("name");
877 frame.WriteString("value2");
878 } else {
879 frame.WriteUInt32(2); // Number of headers.
880 frame.WriteStringPiece32("name");
881 frame.WriteStringPiece32("value1");
882 frame.WriteStringPiece32("name");
883 frame.WriteStringPiece32("value2");
885 // write the length
886 frame.RewriteLength(framer);
888 SpdyHeaderBlock new_headers;
889 framer.set_enable_compression(false);
890 scoped_ptr<SpdyFrame> control_frame(frame.take());
891 base::StringPiece serialized_headers =
892 GetSerializedHeaders(control_frame.get(), framer);
893 // This should fail because duplicate headers are verboten by the spec.
894 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
895 serialized_headers.size(),
896 &new_headers));
899 TEST_P(SpdyFramerTest, MultiValueHeader) {
900 SpdyFramer framer(spdy_version_);
901 // Frame builder with plentiful buffer size.
902 SpdyFrameBuilder frame(1024, spdy_version_);
903 if (spdy_version_ <= SPDY3) {
904 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
905 frame.WriteUInt32(3); // stream_id
906 frame.WriteUInt32(0); // associated stream id
907 frame.WriteUInt16(0); // Priority.
908 } else {
909 frame.BeginNewFrame(framer,
910 HEADERS,
911 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
913 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
914 frame.WriteUInt8(255); // Priority weight.
917 string value("value1\0value2", 13);
918 if (IsSpdy2()) {
919 frame.WriteUInt16(1); // Number of headers.
920 frame.WriteString("name");
921 frame.WriteString(value);
922 } else if (spdy_version_ > SPDY3) {
923 // TODO(jgraettinger): If this pattern appears again, move to test class.
924 std::map<string, string> header_set;
925 header_set["name"] = value;
926 string buffer;
927 HpackEncoder encoder(ObtainHpackHuffmanTable());
928 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
929 frame.WriteBytes(&buffer[0], buffer.size());
930 } else {
931 frame.WriteUInt32(1); // Number of headers.
932 frame.WriteStringPiece32("name");
933 frame.WriteStringPiece32(value);
935 // write the length
936 frame.RewriteLength(framer);
938 framer.set_enable_compression(false);
939 scoped_ptr<SpdyFrame> control_frame(frame.take());
941 TestSpdyVisitor visitor(spdy_version_);
942 visitor.use_compression_ = false;
943 visitor.SimulateInFramer(
944 reinterpret_cast<unsigned char*>(control_frame->data()),
945 control_frame->size());
947 EXPECT_THAT(visitor.headers_,
948 testing::ElementsAre(testing::Pair("name", value)));
951 TEST_P(SpdyFramerTest, BasicCompression) {
952 if (spdy_version_ > SPDY3) {
953 // Deflate compression doesn't apply to HPACK.
954 return;
956 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
957 SpdyFramer framer(spdy_version_);
958 framer.set_debug_visitor(visitor.get());
959 SpdySynStreamIR syn_stream(1);
960 syn_stream.set_priority(1);
961 syn_stream.SetHeader("server", "SpdyServer 1.0");
962 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
963 syn_stream.SetHeader("status", "200");
964 syn_stream.SetHeader("version", "HTTP/1.1");
965 syn_stream.SetHeader("content-type", "text/html");
966 syn_stream.SetHeader("content-length", "12");
967 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
968 size_t uncompressed_size1 = visitor->last_payload_len_;
969 size_t compressed_size1 =
970 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
971 if (IsSpdy2()) {
972 EXPECT_EQ(139u, uncompressed_size1);
973 #if defined(USE_SYSTEM_ZLIB)
974 EXPECT_EQ(155u, compressed_size1);
975 #else // !defined(USE_SYSTEM_ZLIB)
976 EXPECT_EQ(135u, compressed_size1);
977 #endif // !defined(USE_SYSTEM_ZLIB)
978 } else {
979 EXPECT_EQ(165u, uncompressed_size1);
980 #if defined(USE_SYSTEM_ZLIB)
981 EXPECT_EQ(181u, compressed_size1);
982 #else // !defined(USE_SYSTEM_ZLIB)
983 EXPECT_EQ(117u, compressed_size1);
984 #endif // !defined(USE_SYSTEM_ZLIB)
986 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
987 size_t uncompressed_size2 = visitor->last_payload_len_;
988 size_t compressed_size2 =
989 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
991 // Expect the second frame to be more compact than the first.
992 EXPECT_LE(frame2->size(), frame1->size());
994 // Decompress the first frame
995 scoped_ptr<SpdyFrame> frame3(
996 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
998 // Decompress the second frame
999 visitor.reset(new TestSpdyVisitor(spdy_version_));
1000 framer.set_debug_visitor(visitor.get());
1001 scoped_ptr<SpdyFrame> frame4(
1002 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1003 size_t uncompressed_size4 =
1004 frame4->size() - framer.GetSynStreamMinimumSize();
1005 size_t compressed_size4 =
1006 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1007 if (IsSpdy2()) {
1008 EXPECT_EQ(139u, uncompressed_size4);
1009 #if defined(USE_SYSTEM_ZLIB)
1010 EXPECT_EQ(149u, compressed_size4);
1011 #else // !defined(USE_SYSTEM_ZLIB)
1012 EXPECT_EQ(101u, compressed_size4);
1013 #endif // !defined(USE_SYSTEM_ZLIB)
1014 } else {
1015 EXPECT_EQ(165u, uncompressed_size4);
1016 #if defined(USE_SYSTEM_ZLIB)
1017 EXPECT_EQ(175u, compressed_size4);
1018 #else // !defined(USE_SYSTEM_ZLIB)
1019 EXPECT_EQ(102u, compressed_size4);
1020 #endif // !defined(USE_SYSTEM_ZLIB)
1023 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1024 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1025 EXPECT_EQ(compressed_size2, compressed_size4);
1027 // Expect frames 3 & 4 to be the same.
1028 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1030 // Expect frames 3 to be the same as a uncompressed frame created
1031 // from scratch.
1032 framer.set_enable_compression(false);
1033 scoped_ptr<SpdyFrame> uncompressed_frame(
1034 framer.SerializeSynStream(syn_stream));
1035 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1038 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1039 // See crbug.com/172383
1040 SpdyHeadersIR headers(1);
1041 headers.SetHeader("server", "SpdyServer 1.0");
1042 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1043 headers.SetHeader("status", "200");
1044 headers.SetHeader("version", "HTTP/1.1");
1045 headers.SetHeader("content-type", "text/html");
1046 headers.SetHeader("content-length", "12");
1047 headers.SetHeader("x-empty-header", "");
1049 SpdyFramer framer(spdy_version_);
1050 framer.set_enable_compression(true);
1051 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1054 TEST_P(SpdyFramerTest, Basic) {
1055 const unsigned char kV2Input[] = {
1056 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1057 0x00, 0x00, 0x00, 0x14,
1058 0x00, 0x00, 0x00, 0x01,
1059 0x00, 0x00, 0x00, 0x00,
1060 0x00, 0x00, 0x00, 0x01,
1061 0x00, 0x02, 'h', 'h',
1062 0x00, 0x02, 'v', 'v',
1064 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1065 0x00, 0x00, 0x00, 0x18,
1066 0x00, 0x00, 0x00, 0x01,
1067 0x00, 0x00, 0x00, 0x02,
1068 0x00, 0x02, 'h', '2',
1069 0x00, 0x02, 'v', '2',
1070 0x00, 0x02, 'h', '3',
1071 0x00, 0x02, 'v', '3',
1073 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1074 0x00, 0x00, 0x00, 0x0c,
1075 0xde, 0xad, 0xbe, 0xef,
1076 0xde, 0xad, 0xbe, 0xef,
1077 0xde, 0xad, 0xbe, 0xef,
1079 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1080 0x00, 0x00, 0x00, 0x0c,
1081 0x00, 0x00, 0x00, 0x03,
1082 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00,
1085 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1086 0x00, 0x00, 0x00, 0x08,
1087 0xde, 0xad, 0xbe, 0xef,
1088 0xde, 0xad, 0xbe, 0xef,
1090 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1091 0x00, 0x00, 0x00, 0x04,
1092 0xde, 0xad, 0xbe, 0xef,
1094 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1095 0x00, 0x00, 0x00, 0x08,
1096 0x00, 0x00, 0x00, 0x01,
1097 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1099 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1100 0x00, 0x00, 0x00, 0x00,
1102 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1103 0x00, 0x00, 0x00, 0x08,
1104 0x00, 0x00, 0x00, 0x03,
1105 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1108 const unsigned char kV3Input[] = {
1109 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1110 0x00, 0x00, 0x00, 0x1a,
1111 0x00, 0x00, 0x00, 0x01,
1112 0x00, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x01, 0x00, 0x00,
1115 0x00, 0x02, 'h', 'h',
1116 0x00, 0x00, 0x00, 0x02,
1117 'v', 'v',
1119 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1120 0x00, 0x00, 0x00, 0x20,
1121 0x00, 0x00, 0x00, 0x01,
1122 0x00, 0x00, 0x00, 0x02,
1123 0x00, 0x00, 0x00, 0x02,
1124 'h', '2',
1125 0x00, 0x00, 0x00, 0x02,
1126 'v', '2', 0x00, 0x00,
1127 0x00, 0x02, 'h', '3',
1128 0x00, 0x00, 0x00, 0x02,
1129 'v', '3',
1131 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1132 0x00, 0x00, 0x00, 0x0c,
1133 0xde, 0xad, 0xbe, 0xef,
1134 0xde, 0xad, 0xbe, 0xef,
1135 0xde, 0xad, 0xbe, 0xef,
1137 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1138 0x00, 0x00, 0x00, 0x0e,
1139 0x00, 0x00, 0x00, 0x03,
1140 0x00, 0x00, 0x00, 0x00,
1141 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1145 0x00, 0x00, 0x00, 0x08,
1146 0xde, 0xad, 0xbe, 0xef,
1147 0xde, 0xad, 0xbe, 0xef,
1149 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1150 0x00, 0x00, 0x00, 0x04,
1151 0xde, 0xad, 0xbe, 0xef,
1153 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1154 0x00, 0x00, 0x00, 0x08,
1155 0x00, 0x00, 0x00, 0x01,
1156 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1158 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1159 0x00, 0x00, 0x00, 0x00,
1161 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1162 0x00, 0x00, 0x00, 0x08,
1163 0x00, 0x00, 0x00, 0x03,
1164 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1167 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1168 // HEADERS frames with PRIORITY and END_HEADERS set.
1169 const unsigned char kV4Input[] = {
1170 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1171 0x24, 0x00, 0x00, 0x00,
1172 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1173 0x00, 0x82, // :method: GET
1175 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1176 0x04, 0x00, 0x00, 0x00, // Stream 1
1177 0x01, 0x8c, // :status: 200
1179 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1180 0x00, 0x00, 0x00, 0x00,
1181 0x01, 0xde, 0xad, 0xbe,
1182 0xef, 0xde, 0xad, 0xbe,
1183 0xef, 0xde, 0xad, 0xbe,
1184 0xef,
1186 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1187 0x24, 0x00, 0x00, 0x00,
1188 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1189 0x00, 0x82, // :method: GET
1191 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1192 0x00, 0x00, 0x00, 0x00,
1193 0x03, 0xde, 0xad, 0xbe,
1194 0xef, 0xde, 0xad, 0xbe,
1195 0xef,
1197 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1198 0x00, 0x00, 0x00, 0x00,
1199 0x01, 0xde, 0xad, 0xbe,
1200 0xef,
1202 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1203 0x00, 0x00, 0x00, 0x00,
1204 0x01, 0x00, 0x00, 0x00,
1205 0x08, // RST_STREAM_CANCEL
1207 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1208 0x00, 0x00, 0x00, 0x00,
1209 0x03,
1211 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1212 0x00, 0x00, 0x00, 0x00,
1213 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1214 0x08, 0x52, 0x45, 0x53, // opaque data
1215 0x45, 0x54, 0x53, 0x54,
1216 0x52, 0x45, 0x41, 0x4d,
1219 TestSpdyVisitor visitor(spdy_version_);
1220 if (IsSpdy2()) {
1221 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1222 } else if (IsSpdy3()) {
1223 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1224 } else {
1225 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1228 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1229 EXPECT_EQ(24, visitor.data_bytes_);
1230 EXPECT_EQ(0, visitor.error_count_);
1231 EXPECT_EQ(2, visitor.fin_frame_count_);
1233 if (IsSpdy4()) {
1234 EXPECT_EQ(3, visitor.headers_frame_count_);
1235 EXPECT_EQ(0, visitor.syn_frame_count_);
1236 base::StringPiece reset_stream = "RESETSTREAM";
1237 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1238 } else {
1239 EXPECT_EQ(1, visitor.headers_frame_count_);
1240 EXPECT_EQ(2, visitor.syn_frame_count_);
1241 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1244 EXPECT_EQ(0, visitor.fin_flag_count_);
1245 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1246 EXPECT_EQ(4, visitor.data_frame_count_);
1247 visitor.fin_opaque_data_.clear();
1250 // Test that the FIN flag on a data frame signifies EOF.
1251 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1252 const unsigned char kV2Input[] = {
1253 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1254 0x00, 0x00, 0x00, 0x14,
1255 0x00, 0x00, 0x00, 0x01,
1256 0x00, 0x00, 0x00, 0x00,
1257 0x00, 0x00, 0x00, 0x01,
1258 0x00, 0x02, 'h', 'h',
1259 0x00, 0x02, 'v', 'v',
1261 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1262 0x00, 0x00, 0x00, 0x10,
1263 0x00, 0x00, 0x00, 0x01,
1264 0x00, 0x00, 0x00, 0x01,
1265 0x00, 0x02, 'a', 'a',
1266 0x00, 0x02, 'b', 'b',
1268 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1269 0x00, 0x00, 0x00, 0x0c,
1270 0xde, 0xad, 0xbe, 0xef,
1271 0xde, 0xad, 0xbe, 0xef,
1272 0xde, 0xad, 0xbe, 0xef,
1274 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1275 0x01, 0x00, 0x00, 0x04,
1276 0xde, 0xad, 0xbe, 0xef,
1278 const unsigned char kV3Input[] = {
1279 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1280 0x00, 0x00, 0x00, 0x1a,
1281 0x00, 0x00, 0x00, 0x01,
1282 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x01, 0x00, 0x00,
1285 0x00, 0x02, 'h', 'h',
1286 0x00, 0x00, 0x00, 0x02,
1287 'v', 'v',
1289 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1290 0x00, 0x00, 0x00, 0x14,
1291 0x00, 0x00, 0x00, 0x01,
1292 0x00, 0x00, 0x00, 0x01,
1293 0x00, 0x00, 0x00, 0x02,
1294 'a', 'a', 0x00, 0x00,
1295 0x00, 0x02, 'b', 'b',
1297 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1298 0x00, 0x00, 0x00, 0x0c,
1299 0xde, 0xad, 0xbe, 0xef,
1300 0xde, 0xad, 0xbe, 0xef,
1301 0xde, 0xad, 0xbe, 0xef,
1303 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1304 0x01, 0x00, 0x00, 0x04,
1305 0xde, 0xad, 0xbe, 0xef,
1308 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1309 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1310 const unsigned char kV4Input[] = {
1311 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1312 0x24, 0x00, 0x00, 0x00, // Stream 1
1313 0x01, 0x00, 0x00, 0x00, // Priority 0
1314 0x00, 0x82, // :method: GET
1316 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1317 0x04, 0x00, 0x00, 0x00, // Stream 1
1318 0x01, 0x8c, // :status: 200
1320 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1321 0x00, 0x00, 0x00, 0x00,
1322 0x01, 0xde, 0xad, 0xbe,
1323 0xef, 0xde, 0xad, 0xbe,
1324 0xef, 0xde, 0xad, 0xbe,
1325 0xef,
1327 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1328 0x01, 0x00, 0x00, 0x00,
1329 0x01, 0xde, 0xad, 0xbe,
1330 0xef,
1333 TestSpdyVisitor visitor(spdy_version_);
1334 if (IsSpdy2()) {
1335 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1336 } else if (IsSpdy3()) {
1337 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1338 } else {
1339 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1342 EXPECT_EQ(0, visitor.error_count_);
1343 if (IsSpdy4()) {
1344 EXPECT_EQ(0, visitor.syn_frame_count_);
1345 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1346 EXPECT_EQ(2, visitor.headers_frame_count_);
1347 } else {
1348 EXPECT_EQ(1, visitor.syn_frame_count_);
1349 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1350 EXPECT_EQ(0, visitor.headers_frame_count_);
1352 EXPECT_EQ(16, visitor.data_bytes_);
1353 EXPECT_EQ(0, visitor.fin_frame_count_);
1354 EXPECT_EQ(0, visitor.fin_flag_count_);
1355 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1356 EXPECT_EQ(2, visitor.data_frame_count_);
1359 // Test that the FIN flag on a SYN reply frame signifies EOF.
1360 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1361 const unsigned char kV2Input[] = {
1362 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1363 0x01, 0x00, 0x00, 0x00,
1364 0x14, 0x00, 0x00, 0x00,
1365 0x01, 0x00, 0x00, 0x00,
1366 0x00, 0x00, 0x00, 0x00,
1367 0x01, 0x00, 0x02, 'h',
1368 'h', 0x00, 0x02, 'v',
1369 'v',
1371 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1372 0x02, 0x01, 0x00, 0x00,
1373 0x10, 0x00, 0x00, 0x00,
1374 0x01, 0x00, 0x00, 0x00,
1375 0x01, 0x00, 0x02, 'a',
1376 'a', 0x00, 0x02, 'b',
1377 'b',
1379 const unsigned char kV3Input[] = {
1380 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1381 0x01, 0x00, 0x00, 0x00,
1382 0x1a, 0x00, 0x00, 0x00,
1383 0x01, 0x00, 0x00, 0x00,
1384 0x00, 0x00, 0x00, 0x00,
1385 0x00, 0x00, 0x01, 0x00,
1386 0x00, 0x00, 0x02, 'h',
1387 'h', 0x00, 0x00, 0x00,
1388 0x02, 'v', 'v',
1390 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1391 0x02, 0x01, 0x00, 0x00,
1392 0x14, 0x00, 0x00, 0x00,
1393 0x01, 0x00, 0x00, 0x00,
1394 0x01, 0x00, 0x00, 0x00,
1395 0x02, 'a', 'a', 0x00,
1396 0x00, 0x00, 0x02, 'b',
1397 'b',
1400 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1401 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1402 const unsigned char kV4Input[] = {
1403 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1404 0x24, 0x00, 0x00, 0x00,
1405 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1406 0x00, 0x82, // :method: GET
1408 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1409 0x05, 0x00, 0x00, 0x00,
1410 0x01, 0x8c, // Stream 1, :status: 200
1413 TestSpdyVisitor visitor(spdy_version_);
1414 if (IsSpdy2()) {
1415 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1416 } else if (IsSpdy3()) {
1417 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1418 } else {
1419 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1422 EXPECT_EQ(0, visitor.error_count_);
1423 if (IsSpdy4()) {
1424 EXPECT_EQ(0, visitor.syn_frame_count_);
1425 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1426 EXPECT_EQ(2, visitor.headers_frame_count_);
1427 } else {
1428 EXPECT_EQ(1, visitor.syn_frame_count_);
1429 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1430 EXPECT_EQ(0, visitor.headers_frame_count_);
1432 EXPECT_EQ(0, visitor.data_bytes_);
1433 EXPECT_EQ(0, visitor.fin_frame_count_);
1434 EXPECT_EQ(1, visitor.fin_flag_count_);
1435 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1436 EXPECT_EQ(0, visitor.data_frame_count_);
1439 TEST_P(SpdyFramerTest, HeaderCompression) {
1440 if (spdy_version_ > SPDY3) {
1441 // Deflate compression doesn't apply to HPACK.
1442 return;
1444 SpdyFramer send_framer(spdy_version_);
1445 SpdyFramer recv_framer(spdy_version_);
1447 send_framer.set_enable_compression(true);
1448 recv_framer.set_enable_compression(true);
1450 const char kHeader1[] = "header1";
1451 const char kHeader2[] = "header2";
1452 const char kHeader3[] = "header3";
1453 const char kValue1[] = "value1";
1454 const char kValue2[] = "value2";
1455 const char kValue3[] = "value3";
1457 // SYN_STREAM #1
1458 SpdyHeaderBlock block;
1459 block[kHeader1] = kValue1;
1460 block[kHeader2] = kValue2;
1461 SpdySynStreamIR syn_ir_1(1);
1462 syn_ir_1.set_name_value_block(block);
1463 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1464 EXPECT_TRUE(syn_frame_1.get() != NULL);
1466 // SYN_STREAM #2
1467 block[kHeader3] = kValue3;
1468 SpdySynStreamIR syn_stream(3);
1469 syn_stream.set_name_value_block(block);
1470 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1471 EXPECT_TRUE(syn_frame_2.get() != NULL);
1473 // Now start decompressing
1474 scoped_ptr<SpdyFrame> decompressed;
1475 scoped_ptr<SpdyFrame> uncompressed;
1476 base::StringPiece serialized_headers;
1477 SpdyHeaderBlock decompressed_headers;
1479 // Decompress SYN_STREAM #1
1480 decompressed.reset(
1481 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1482 EXPECT_TRUE(decompressed.get() != NULL);
1483 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1484 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1485 serialized_headers.size(),
1486 &decompressed_headers));
1487 EXPECT_EQ(2u, decompressed_headers.size());
1488 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1489 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1491 // Decompress SYN_STREAM #2
1492 decompressed.reset(
1493 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1494 EXPECT_TRUE(decompressed.get() != NULL);
1495 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1496 decompressed_headers.clear();
1497 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1498 serialized_headers.size(),
1499 &decompressed_headers));
1500 EXPECT_EQ(3u, decompressed_headers.size());
1501 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1502 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1503 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1506 // Verify we can decompress the stream even if handed over to the
1507 // framer 1 byte at a time.
1508 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1509 SpdyFramer send_framer(spdy_version_);
1511 send_framer.set_enable_compression(true);
1513 const char kHeader1[] = "header1";
1514 const char kHeader2[] = "header2";
1515 const char kValue1[] = "value1";
1516 const char kValue2[] = "value2";
1518 SpdyHeadersIR headers(1);
1519 headers.SetHeader(kHeader1, kValue1);
1520 headers.SetHeader(kHeader2, kValue2);
1521 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1522 EXPECT_TRUE(headers_frame.get() != NULL);
1524 const char bytes[] = "this is a test test test test test!";
1525 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1526 data_ir.set_fin(true);
1527 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1528 EXPECT_TRUE(send_frame.get() != NULL);
1530 // Run the inputs through the framer.
1531 TestSpdyVisitor visitor(spdy_version_);
1532 visitor.use_compression_ = true;
1533 const unsigned char* data;
1534 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1535 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1536 visitor.SimulateInFramer(data + idx, 1);
1537 ASSERT_EQ(0, visitor.error_count_);
1539 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1540 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1541 visitor.SimulateInFramer(data + idx, 1);
1542 ASSERT_EQ(0, visitor.error_count_);
1545 EXPECT_EQ(0, visitor.error_count_);
1546 EXPECT_EQ(0, visitor.syn_frame_count_);
1547 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1548 EXPECT_EQ(1, visitor.headers_frame_count_);
1549 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1550 EXPECT_EQ(0, visitor.fin_frame_count_);
1551 EXPECT_EQ(0, visitor.fin_flag_count_);
1552 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1553 EXPECT_EQ(1, visitor.data_frame_count_);
1556 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1557 SpdyFramer framer(spdy_version_);
1558 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1559 SpdyWindowUpdateIR(1, 0x12345678)));
1561 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1562 const unsigned char kV3FrameData[] = { // Also applies for V2.
1563 0x80, spdy_version_ch_, 0x00, 0x09,
1564 0x00, 0x00, 0x00, 0x08,
1565 0x00, 0x00, 0x00, 0x01,
1566 0x12, 0x34, 0x56, 0x78
1568 const unsigned char kV4FrameData[] = {
1569 0x00, 0x00, 0x04, 0x08,
1570 0x00, 0x00, 0x00, 0x00,
1571 0x01, 0x12, 0x34, 0x56,
1572 0x78
1575 if (IsSpdy4()) {
1576 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1577 } else {
1578 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1582 TEST_P(SpdyFramerTest, CreateDataFrame) {
1583 SpdyFramer framer(spdy_version_);
1586 const char kDescription[] = "'hello' data frame, no FIN";
1587 const unsigned char kV3FrameData[] = { // Also applies for V2.
1588 0x00, 0x00, 0x00, 0x01,
1589 0x00, 0x00, 0x00, 0x05,
1590 'h', 'e', 'l', 'l',
1593 const unsigned char kV4FrameData[] = {
1594 0x00, 0x00, 0x05, 0x00,
1595 0x00, 0x00, 0x00, 0x00,
1596 0x01, 'h', 'e', 'l',
1597 'l', 'o'
1599 const char bytes[] = "hello";
1601 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1602 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1603 if (IsSpdy4()) {
1604 CompareFrame(
1605 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1606 } else {
1607 CompareFrame(
1608 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1611 SpdyDataIR data_header_ir(1);
1612 data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
1613 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1614 data_header_ir));
1615 CompareCharArraysWithHexError(
1616 kDescription,
1617 reinterpret_cast<const unsigned char*>(frame->data()),
1618 framer.GetDataFrameMinimumSize(),
1619 IsSpdy4() ? kV4FrameData : kV3FrameData,
1620 framer.GetDataFrameMinimumSize());
1624 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1625 const unsigned char kV3FrameData[] = { // Also applies for V2.
1626 0x00, 0x00, 0x00, 0x01,
1627 0x00, 0x00, 0x00, 0x05,
1628 'h', 'e', 'l', 'l',
1632 const unsigned char kV4FrameData[] = {
1633 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1634 0x08, 0x00, 0x00, 0x00,
1635 0x01, 0xf7, // Pad length field.
1636 'h', 'e', 'l', 'l', // Data
1637 'o',
1638 // Padding of 247 0x00(s).
1639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
1661 const char bytes[] = "hello";
1663 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1664 // 247 zeros and the pad length field make the overall padding to be 248
1665 // bytes.
1666 data_ir.set_padding_len(248);
1667 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1668 if (IsSpdy4()) {
1669 CompareFrame(
1670 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1671 } else {
1672 CompareFrame(
1673 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1676 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1677 CompareCharArraysWithHexError(
1678 kDescription,
1679 reinterpret_cast<const unsigned char*>(frame->data()),
1680 framer.GetDataFrameMinimumSize(),
1681 IsSpdy4() ? kV4FrameData : kV3FrameData,
1682 framer.GetDataFrameMinimumSize());
1686 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1687 const unsigned char kV3FrameData[] = { // Also applies for V2.
1688 0x00, 0x00, 0x00, 0x01,
1689 0x00, 0x00, 0x00, 0x05,
1690 'h', 'e', 'l', 'l',
1694 const unsigned char kV4FrameData[] = {
1695 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1696 0x08, 0x00, 0x00, 0x00,
1697 0x01, 0x07, // Pad length field.
1698 'h', 'e', 'l', 'l', // Data
1699 'o',
1700 0x00, 0x00, 0x00, 0x00, // Padding
1701 0x00, 0x00, 0x00
1703 const char bytes[] = "hello";
1705 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1706 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1707 data_ir.set_padding_len(8);
1708 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1709 if (IsSpdy4()) {
1710 CompareFrame(
1711 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1712 } else {
1713 CompareFrame(
1714 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1719 const char kDescription[] =
1720 "'hello' data frame with 1 byte padding, no FIN";
1721 const unsigned char kV3FrameData[] = { // Also applies for V2.
1722 0x00, 0x00, 0x00, 0x01,
1723 0x00, 0x00, 0x00, 0x05,
1724 'h', 'e', 'l', 'l',
1728 const unsigned char kV4FrameData[] = {
1729 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1730 0x08, 0x00, 0x00, 0x00,
1731 0x01, 0x00, // Pad length field.
1732 'h', 'e', 'l', 'l', // Data
1733 'o',
1735 const char bytes[] = "hello";
1737 SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
1738 // The pad length field itself is used for the 1-byte padding and no padding
1739 // payload is needed.
1740 data_ir.set_padding_len(1);
1741 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1742 if (IsSpdy4()) {
1743 CompareFrame(
1744 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1745 } else {
1746 CompareFrame(
1747 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1750 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1751 CompareCharArraysWithHexError(
1752 kDescription,
1753 reinterpret_cast<const unsigned char*>(frame->data()),
1754 framer.GetDataFrameMinimumSize(),
1755 IsSpdy4() ? kV4FrameData : kV3FrameData,
1756 framer.GetDataFrameMinimumSize());
1760 const char kDescription[] = "Data frame with negative data byte, no FIN";
1761 const unsigned char kV3FrameData[] = { // Also applies for V2.
1762 0x00, 0x00, 0x00, 0x01,
1763 0x00, 0x00, 0x00, 0x01,
1764 0xff
1766 const unsigned char kV4FrameData[] = {
1767 0x00, 0x00, 0x01, 0x00, 0x00,
1768 0x00, 0x00, 0x00, 0x01,
1769 0xff
1771 SpdyDataIR data_ir(1, StringPiece("\xff", 1));
1772 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1773 if (IsSpdy4()) {
1774 CompareFrame(
1775 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1776 } else {
1777 CompareFrame(
1778 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1783 const char kDescription[] = "'hello' data frame, with FIN";
1784 const unsigned char kV3FrameData[] = { // Also applies for V2.
1785 0x00, 0x00, 0x00, 0x01,
1786 0x01, 0x00, 0x00, 0x05,
1787 'h', 'e', 'l', 'l',
1790 const unsigned char kV4FrameData[] = {
1791 0x00, 0x00, 0x05, 0x00,
1792 0x01, 0x00, 0x00, 0x00,
1793 0x01, 'h', 'e', 'l',
1794 'l', 'o'
1796 SpdyDataIR data_ir(1, StringPiece("hello", 5));
1797 data_ir.set_fin(true);
1798 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1799 if (IsSpdy4()) {
1800 CompareFrame(
1801 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1802 } else {
1803 CompareFrame(
1804 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1809 const char kDescription[] = "Empty data frame";
1810 const unsigned char kV3FrameData[] = { // Also applies for V2.
1811 0x00, 0x00, 0x00, 0x01,
1812 0x00, 0x00, 0x00, 0x00,
1814 const unsigned char kV4FrameData[] = {
1815 0x00, 0x00, 0x00, 0x00,
1816 0x00, 0x00, 0x00, 0x00,
1817 0x01,
1819 SpdyDataIR data_ir(1, StringPiece());
1820 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1821 if (IsSpdy4()) {
1822 CompareFrame(
1823 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1824 } else {
1825 CompareFrame(
1826 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1829 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1830 CompareCharArraysWithHexError(
1831 kDescription,
1832 reinterpret_cast<const unsigned char*>(frame->data()),
1833 framer.GetDataFrameMinimumSize(),
1834 IsSpdy4() ? kV4FrameData : kV3FrameData,
1835 framer.GetDataFrameMinimumSize());
1839 const char kDescription[] = "Data frame with max stream ID";
1840 const unsigned char kV3FrameData[] = { // Also applies for V2.
1841 0x7f, 0xff, 0xff, 0xff,
1842 0x01, 0x00, 0x00, 0x05,
1843 'h', 'e', 'l', 'l',
1846 const unsigned char kV4FrameData[] = {
1847 0x00, 0x00, 0x05, 0x00,
1848 0x01, 0x7f, 0xff, 0xff,
1849 0xff, 'h', 'e', 'l',
1850 'l', 'o'
1852 SpdyDataIR data_ir(0x7fffffff, "hello");
1853 data_ir.set_fin(true);
1854 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1855 if (IsSpdy4()) {
1856 CompareFrame(
1857 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1858 } else {
1859 CompareFrame(
1860 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1864 if (!IsSpdy4()) {
1865 // This test does not apply to SPDY 4 because the max frame size is smaller
1866 // than 4MB.
1867 const char kDescription[] = "Large data frame";
1868 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1869 const string kData(kDataSize, 'A');
1870 const unsigned char kFrameHeader[] = {
1871 0x00, 0x00, 0x00, 0x01,
1872 0x01, 0x40, 0x00, 0x00,
1875 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1876 scoped_ptr<unsigned char[]> expected_frame_data(
1877 new unsigned char[kFrameSize]);
1878 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1879 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1881 SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
1882 data_ir.set_fin(true);
1883 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1884 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1888 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1889 if (!IsSpdy2() && !IsSpdy3()) {
1890 // SYN_STREAM unsupported in SPDY>3
1891 return;
1893 SpdyFramer framer(spdy_version_);
1894 framer.set_enable_compression(false);
1897 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1899 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1900 const unsigned char kV2FrameData[] = {
1901 0x80, spdy_version_ch_, 0x00, 0x01,
1902 0x00, 0x00, 0x00, 0x20,
1903 0x00, 0x00, 0x00, 0x01,
1904 0x00, 0x00, 0x00, 0x00,
1905 kPri, 0x00, 0x00, 0x02,
1906 0x00, 0x03, 'b', 'a',
1907 'r', 0x00, 0x03, 'f',
1908 'o', 'o', 0x00, 0x03,
1909 'f', 'o', 'o', 0x00,
1910 0x03, 'b', 'a', 'r'
1912 const unsigned char kV3FrameData[] = {
1913 0x80, spdy_version_ch_, 0x00, 0x01,
1914 0x00, 0x00, 0x00, 0x2a,
1915 0x00, 0x00, 0x00, 0x01,
1916 0x00, 0x00, 0x00, 0x00,
1917 kPri, 0x00, 0x00, 0x00,
1918 0x00, 0x02, 0x00, 0x00,
1919 0x00, 0x03, 'b', 'a',
1920 'r', 0x00, 0x00, 0x00,
1921 0x03, 'f', 'o', 'o',
1922 0x00, 0x00, 0x00, 0x03,
1923 'f', 'o', 'o', 0x00,
1924 0x00, 0x00, 0x03, 'b',
1925 'a', 'r'
1927 SpdySynStreamIR syn_stream(1);
1928 syn_stream.set_priority(framer.GetLowestPriority());
1929 syn_stream.SetHeader("bar", "foo");
1930 syn_stream.SetHeader("foo", "bar");
1931 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1932 if (IsSpdy2()) {
1933 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1934 } else if (IsSpdy3()) {
1935 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1936 } else {
1937 LOG(FATAL) << "Unsupported version in test.";
1942 const char kDescription[] =
1943 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1944 "max stream ID";
1946 const unsigned char kV2FrameData[] = {
1947 0x80, spdy_version_ch_, 0x00, 0x01,
1948 0x01, 0x00, 0x00, 0x1D,
1949 0x7f, 0xff, 0xff, 0xff,
1950 0x7f, 0xff, 0xff, 0xff,
1951 0x00, 0x00, 0x00, 0x02,
1952 0x00, 0x00, 0x00, 0x03,
1953 'f', 'o', 'o', 0x00,
1954 0x03, 'f', 'o', 'o',
1955 0x00, 0x03, 'b', 'a',
1958 const unsigned char kV3FrameData[] = {
1959 0x80, spdy_version_ch_, 0x00, 0x01,
1960 0x01, 0x00, 0x00, 0x27,
1961 0x7f, 0xff, 0xff, 0xff,
1962 0x7f, 0xff, 0xff, 0xff,
1963 0x00, 0x00, 0x00, 0x00,
1964 0x00, 0x02, 0x00, 0x00,
1965 0x00, 0x00, 0x00, 0x00,
1966 0x00, 0x03, 'f', 'o',
1967 'o', 0x00, 0x00, 0x00,
1968 0x03, 'f', 'o', 'o',
1969 0x00, 0x00, 0x00, 0x03,
1970 'b', 'a', 'r'
1972 SpdySynStreamIR syn_stream(0x7fffffff);
1973 syn_stream.set_associated_to_stream_id(0x7fffffff);
1974 syn_stream.set_priority(framer.GetHighestPriority());
1975 syn_stream.set_fin(true);
1976 syn_stream.SetHeader("", "foo");
1977 syn_stream.SetHeader("foo", "bar");
1978 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1979 if (IsSpdy2()) {
1980 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1981 } else if (IsSpdy3()) {
1982 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1983 } else {
1984 LOG(FATAL) << "Unsupported version in test.";
1989 const char kDescription[] =
1990 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1991 "max stream ID";
1993 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
1994 const unsigned char kV2FrameData[] = {
1995 0x80, spdy_version_ch_, 0x00, 0x01,
1996 0x01, 0x00, 0x00, 0x1D,
1997 0x7f, 0xff, 0xff, 0xff,
1998 0x7f, 0xff, 0xff, 0xff,
1999 kPri, 0x00, 0x00, 0x02,
2000 0x00, 0x03, 'b', 'a',
2001 'r', 0x00, 0x03, 'f',
2002 'o', 'o', 0x00, 0x03,
2003 'f', 'o', 'o', 0x00,
2004 0x00
2006 const unsigned char kV3FrameData[] = {
2007 0x80, spdy_version_ch_, 0x00, 0x01,
2008 0x01, 0x00, 0x00, 0x27,
2009 0x7f, 0xff, 0xff, 0xff,
2010 0x7f, 0xff, 0xff, 0xff,
2011 kPri, 0x00, 0x00, 0x00,
2012 0x00, 0x02, 0x00, 0x00,
2013 0x00, 0x03, 'b', 'a',
2014 'r', 0x00, 0x00, 0x00,
2015 0x03, 'f', 'o', 'o',
2016 0x00, 0x00, 0x00, 0x03,
2017 'f', 'o', 'o', 0x00,
2018 0x00, 0x00, 0x00
2020 SpdySynStreamIR syn_stream(0x7fffffff);
2021 syn_stream.set_associated_to_stream_id(0x7fffffff);
2022 syn_stream.set_priority(1);
2023 syn_stream.set_fin(true);
2024 syn_stream.SetHeader("bar", "foo");
2025 syn_stream.SetHeader("foo", "");
2026 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2027 if (IsSpdy2()) {
2028 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2029 } else if (IsSpdy3()) {
2030 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2031 } else {
2032 LOG(FATAL) << "Unsupported version in test.";
2037 // TODO(phajdan.jr): Clean up after we no longer need
2038 // to workaround http://crbug.com/139744.
2039 #if !defined(USE_SYSTEM_ZLIB)
2040 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2041 if (!IsSpdy2() && !IsSpdy3()) {
2042 // SYN_STREAM not supported for SPDY>3
2043 return;
2045 SpdyFramer framer(spdy_version_);
2046 framer.set_enable_compression(true);
2049 const char kDescription[] =
2050 "SYN_STREAM frame, low pri, no FIN";
2051 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2053 const unsigned char kV2FrameData[] = {
2054 0x80, spdy_version_ch_, 0x00, 0x01,
2055 0x00, 0x00, 0x00, 0x36,
2056 0x00, 0x00, 0x00, 0x01,
2057 0x00, 0x00, 0x00, 0x00,
2058 0x80, 0x00, 0x38, 0xea,
2059 0xdf, 0xa2, 0x51, 0xb2,
2060 0x62, 0x60, 0x62, 0x60,
2061 0x4e, 0x4a, 0x2c, 0x62,
2062 0x60, 0x06, 0x08, 0xa0,
2063 0xb4, 0xfc, 0x7c, 0x80,
2064 0x00, 0x62, 0x60, 0x4e,
2065 0xcb, 0xcf, 0x67, 0x60,
2066 0x06, 0x08, 0xa0, 0xa4,
2067 0xc4, 0x22, 0x80, 0x00,
2068 0x02, 0x00, 0x00, 0x00,
2069 0xff, 0xff,
2071 const unsigned char kV3FrameData[] = {
2072 0x80, spdy_version_ch_, 0x00, 0x01,
2073 0x00, 0x00, 0x00, 0x37,
2074 0x00, 0x00, 0x00, 0x01,
2075 0x00, 0x00, 0x00, 0x00,
2076 0x80, 0x00, 0x38, 0xEA,
2077 0xE3, 0xC6, 0xA7, 0xC2,
2078 0x02, 0xE5, 0x0E, 0x50,
2079 0xC2, 0x4B, 0x4A, 0x04,
2080 0xE5, 0x0B, 0x66, 0x80,
2081 0x00, 0x4A, 0xCB, 0xCF,
2082 0x07, 0x08, 0x20, 0x10,
2083 0x95, 0x96, 0x9F, 0x0F,
2084 0xA2, 0x00, 0x02, 0x28,
2085 0x29, 0xB1, 0x08, 0x20,
2086 0x80, 0x00, 0x00, 0x00,
2087 0x00, 0xFF, 0xFF,
2089 const unsigned char kV2SIMDFrameData[] = {
2090 0x80, spdy_version_ch_, 0x00, 0x01,
2091 0x00, 0x00, 0x00, 0x33,
2092 0x00, 0x00, 0x00, 0x01,
2093 0x00, 0x00, 0x00, 0x00,
2094 0x80, 0x00, 0x38, 0xea,
2095 0xdf, 0xa2, 0x51, 0xb2,
2096 0x62, 0x60, 0x62, 0x60,
2097 0x4e, 0x4a, 0x2c, 0x62,
2098 0x60, 0x06, 0x08, 0xa0,
2099 0xb4, 0xfc, 0x7c, 0x80,
2100 0x00, 0x62, 0x60, 0x06,
2101 0x13, 0x00, 0x01, 0x94,
2102 0x94, 0x58, 0x04, 0x10,
2103 0x40, 0x00, 0x00, 0x00,
2104 0x00, 0xff, 0xff,
2106 const unsigned char kV3SIMDFrameData[] = {
2107 0x80, spdy_version_ch_, 0x00, 0x01,
2108 0x00, 0x00, 0x00, 0x32,
2109 0x00, 0x00, 0x00, 0x01,
2110 0x00, 0x00, 0x00, 0x00,
2111 0x80, 0x00, 0x38, 0xea,
2112 0xe3, 0xc6, 0xa7, 0xc2,
2113 0x02, 0xe5, 0x0e, 0x50,
2114 0xc2, 0x4b, 0x4a, 0x04,
2115 0xe5, 0x0b, 0x66, 0x80,
2116 0x00, 0x4a, 0xcb, 0xcf,
2117 0x07, 0x08, 0x20, 0x24,
2118 0x0a, 0x20, 0x80, 0x92,
2119 0x12, 0x8b, 0x00, 0x02,
2120 0x08, 0x00, 0x00, 0x00,
2121 0xff, 0xff,
2124 SpdySynStreamIR syn_stream(1);
2125 syn_stream.set_priority(priority);
2126 syn_stream.SetHeader("bar", "foo");
2127 syn_stream.SetHeader("foo", "bar");
2128 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2129 const unsigned char* frame_data =
2130 reinterpret_cast<const unsigned char*>(frame->data());
2131 if (IsSpdy2()) {
2132 // Try comparing with SIMD version, if that fails, do a failing check
2133 // with pretty printing against non-SIMD version
2134 if (memcmp(frame_data,
2135 kV2SIMDFrameData,
2136 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2137 CompareCharArraysWithHexError(kDescription,
2138 frame_data,
2139 frame->size(),
2140 kV2FrameData,
2141 arraysize(kV2FrameData));
2143 } else if (IsSpdy3()) {
2144 if (memcmp(frame_data,
2145 kV3SIMDFrameData,
2146 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2147 CompareCharArraysWithHexError(kDescription,
2148 frame_data,
2149 frame->size(),
2150 kV3FrameData,
2151 arraysize(kV3FrameData));
2153 } else {
2154 LOG(FATAL) << "Unsupported version in test.";
2158 #endif // !defined(USE_SYSTEM_ZLIB)
2160 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2161 if (spdy_version_ > SPDY3) {
2162 // SYN_REPLY unsupported in SPDY>3
2163 return;
2165 SpdyFramer framer(spdy_version_);
2166 framer.set_enable_compression(false);
2169 const char kDescription[] = "SYN_REPLY frame, no FIN";
2171 const unsigned char kV2FrameData[] = {
2172 0x80, spdy_version_ch_, 0x00, 0x02,
2173 0x00, 0x00, 0x00, 0x1C,
2174 0x00, 0x00, 0x00, 0x01,
2175 0x00, 0x00, 0x00, 0x02,
2176 0x00, 0x03, 'b', 'a',
2177 'r', 0x00, 0x03, 'f',
2178 'o', 'o', 0x00, 0x03,
2179 'f', 'o', 'o', 0x00,
2180 0x03, 'b', 'a', 'r'
2182 const unsigned char kV3FrameData[] = {
2183 0x80, spdy_version_ch_, 0x00, 0x02,
2184 0x00, 0x00, 0x00, 0x24,
2185 0x00, 0x00, 0x00, 0x01,
2186 0x00, 0x00, 0x00, 0x02,
2187 0x00, 0x00, 0x00, 0x03,
2188 'b', 'a', 'r', 0x00,
2189 0x00, 0x00, 0x03, 'f',
2190 'o', 'o', 0x00, 0x00,
2191 0x00, 0x03, 'f', 'o',
2192 'o', 0x00, 0x00, 0x00,
2193 0x03, 'b', 'a', 'r'
2195 SpdySynReplyIR syn_reply(1);
2196 syn_reply.SetHeader("bar", "foo");
2197 syn_reply.SetHeader("foo", "bar");
2198 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2199 if (IsSpdy2()) {
2200 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2201 } else if (IsSpdy3()) {
2202 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2203 } else {
2204 LOG(FATAL) << "Unsupported version in test.";
2209 const char kDescription[] =
2210 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2212 const unsigned char kV2FrameData[] = {
2213 0x80, spdy_version_ch_, 0x00, 0x02,
2214 0x01, 0x00, 0x00, 0x19,
2215 0x7f, 0xff, 0xff, 0xff,
2216 0x00, 0x00, 0x00, 0x02,
2217 0x00, 0x00, 0x00, 0x03,
2218 'f', 'o', 'o', 0x00,
2219 0x03, 'f', 'o', 'o',
2220 0x00, 0x03, 'b', 'a',
2223 const unsigned char kV3FrameData[] = {
2224 0x80, spdy_version_ch_, 0x00, 0x02,
2225 0x01, 0x00, 0x00, 0x21,
2226 0x7f, 0xff, 0xff, 0xff,
2227 0x00, 0x00, 0x00, 0x02,
2228 0x00, 0x00, 0x00, 0x00,
2229 0x00, 0x00, 0x00, 0x03,
2230 'f', 'o', 'o', 0x00,
2231 0x00, 0x00, 0x03, 'f',
2232 'o', 'o', 0x00, 0x00,
2233 0x00, 0x03, 'b', 'a',
2236 SpdySynReplyIR syn_reply(0x7fffffff);
2237 syn_reply.set_fin(true);
2238 syn_reply.SetHeader("", "foo");
2239 syn_reply.SetHeader("foo", "bar");
2240 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2241 if (IsSpdy2()) {
2242 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2243 } else if (IsSpdy3()) {
2244 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2245 } else {
2246 LOG(FATAL) << "Unsupported version in test.";
2251 const char kDescription[] =
2252 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2254 const unsigned char kV2FrameData[] = {
2255 0x80, spdy_version_ch_, 0x00, 0x02,
2256 0x01, 0x00, 0x00, 0x19,
2257 0x7f, 0xff, 0xff, 0xff,
2258 0x00, 0x00, 0x00, 0x02,
2259 0x00, 0x03, 'b', 'a',
2260 'r', 0x00, 0x03, 'f',
2261 'o', 'o', 0x00, 0x03,
2262 'f', 'o', 'o', 0x00,
2263 0x00
2265 const unsigned char kV3FrameData[] = {
2266 0x80, spdy_version_ch_, 0x00, 0x02,
2267 0x01, 0x00, 0x00, 0x21,
2268 0x7f, 0xff, 0xff, 0xff,
2269 0x00, 0x00, 0x00, 0x02,
2270 0x00, 0x00, 0x00, 0x03,
2271 'b', 'a', 'r', 0x00,
2272 0x00, 0x00, 0x03, 'f',
2273 'o', 'o', 0x00, 0x00,
2274 0x00, 0x03, 'f', 'o',
2275 'o', 0x00, 0x00, 0x00,
2276 0x00
2278 SpdySynReplyIR syn_reply(0x7fffffff);
2279 syn_reply.set_fin(true);
2280 syn_reply.SetHeader("bar", "foo");
2281 syn_reply.SetHeader("foo", "");
2282 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2283 if (IsSpdy2()) {
2284 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2285 } else if (IsSpdy3()) {
2286 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2287 } else {
2288 LOG(FATAL) << "Unsupported version in test.";
2293 // TODO(phajdan.jr): Clean up after we no longer need
2294 // to workaround http://crbug.com/139744.
2295 #if !defined(USE_SYSTEM_ZLIB)
2296 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2297 if (spdy_version_ > SPDY3) {
2298 // SYN_REPLY unsupported in SPDY>3
2299 return;
2301 SpdyFramer framer(spdy_version_);
2302 framer.set_enable_compression(true);
2305 const char kDescription[] = "SYN_REPLY frame, no FIN";
2307 const unsigned char kV2FrameData[] = {
2308 0x80, spdy_version_ch_, 0x00, 0x02,
2309 0x00, 0x00, 0x00, 0x32,
2310 0x00, 0x00, 0x00, 0x01,
2311 0x00, 0x00, 0x38, 0xea,
2312 0xdf, 0xa2, 0x51, 0xb2,
2313 0x62, 0x60, 0x62, 0x60,
2314 0x4e, 0x4a, 0x2c, 0x62,
2315 0x60, 0x06, 0x08, 0xa0,
2316 0xb4, 0xfc, 0x7c, 0x80,
2317 0x00, 0x62, 0x60, 0x4e,
2318 0xcb, 0xcf, 0x67, 0x60,
2319 0x06, 0x08, 0xa0, 0xa4,
2320 0xc4, 0x22, 0x80, 0x00,
2321 0x02, 0x00, 0x00, 0x00,
2322 0xff, 0xff,
2324 const unsigned char kV3FrameData[] = {
2325 0x80, spdy_version_ch_, 0x00, 0x02,
2326 0x00, 0x00, 0x00, 0x31,
2327 0x00, 0x00, 0x00, 0x01,
2328 0x38, 0xea, 0xe3, 0xc6,
2329 0xa7, 0xc2, 0x02, 0xe5,
2330 0x0e, 0x50, 0xc2, 0x4b,
2331 0x4a, 0x04, 0xe5, 0x0b,
2332 0x66, 0x80, 0x00, 0x4a,
2333 0xcb, 0xcf, 0x07, 0x08,
2334 0x20, 0x10, 0x95, 0x96,
2335 0x9f, 0x0f, 0xa2, 0x00,
2336 0x02, 0x28, 0x29, 0xb1,
2337 0x08, 0x20, 0x80, 0x00,
2338 0x00, 0x00, 0x00, 0xff,
2339 0xff,
2341 const unsigned char kV2SIMDFrameData[] = {
2342 0x80, spdy_version_ch_, 0x00, 0x02,
2343 0x00, 0x00, 0x00, 0x2f,
2344 0x00, 0x00, 0x00, 0x01,
2345 0x00, 0x00, 0x38, 0xea,
2346 0xdf, 0xa2, 0x51, 0xb2,
2347 0x62, 0x60, 0x62, 0x60,
2348 0x4e, 0x4a, 0x2c, 0x62,
2349 0x60, 0x06, 0x08, 0xa0,
2350 0xb4, 0xfc, 0x7c, 0x80,
2351 0x00, 0x62, 0x60, 0x06,
2352 0x13, 0x00, 0x01, 0x94,
2353 0x94, 0x58, 0x04, 0x10,
2354 0x40, 0x00, 0x00, 0x00,
2355 0x00, 0xff, 0xff,
2357 const unsigned char kV3SIMDFrameData[] = {
2358 0x80, spdy_version_ch_, 0x00, 0x02,
2359 0x00, 0x00, 0x00, 0x2c,
2360 0x00, 0x00, 0x00, 0x01,
2361 0x38, 0xea, 0xe3, 0xc6,
2362 0xa7, 0xc2, 0x02, 0xe5,
2363 0x0e, 0x50, 0xc2, 0x4b,
2364 0x4a, 0x04, 0xe5, 0x0b,
2365 0x66, 0x80, 0x00, 0x4a,
2366 0xcb, 0xcf, 0x07, 0x08,
2367 0x20, 0x24, 0x0a, 0x20,
2368 0x80, 0x92, 0x12, 0x8b,
2369 0x00, 0x02, 0x08, 0x00,
2370 0x00, 0x00, 0xff, 0xff,
2373 SpdySynReplyIR syn_reply(1);
2374 syn_reply.SetHeader("bar", "foo");
2375 syn_reply.SetHeader("foo", "bar");
2376 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2377 const unsigned char* frame_data =
2378 reinterpret_cast<const unsigned char*>(frame->data());
2379 if (IsSpdy2()) {
2380 // Try comparing with SIMD version, if that fails, do a failing check
2381 // with pretty printing against non-SIMD version
2382 if (memcmp(frame_data,
2383 kV2SIMDFrameData,
2384 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2385 CompareCharArraysWithHexError(kDescription,
2386 frame_data,
2387 frame->size(),
2388 kV2FrameData,
2389 arraysize(kV2FrameData));
2391 } else if (IsSpdy3()) {
2392 if (memcmp(frame_data,
2393 kV3SIMDFrameData,
2394 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2395 CompareCharArraysWithHexError(kDescription,
2396 frame_data,
2397 frame->size(),
2398 kV3FrameData,
2399 arraysize(kV3FrameData));
2401 } else {
2402 LOG(FATAL) << "Unsupported version in test.";
2406 #endif // !defined(USE_SYSTEM_ZLIB)
2408 TEST_P(SpdyFramerTest, CreateRstStream) {
2409 SpdyFramer framer(spdy_version_);
2412 const char kDescription[] = "RST_STREAM frame";
2413 const unsigned char kV3FrameData[] = { // Also applies for V2.
2414 0x80, spdy_version_ch_, 0x00, 0x03,
2415 0x00, 0x00, 0x00, 0x08,
2416 0x00, 0x00, 0x00, 0x01,
2417 0x00, 0x00, 0x00, 0x01,
2419 const unsigned char kV4FrameData[] = {
2420 0x00, 0x00, 0x07, 0x03,
2421 0x00, 0x00, 0x00, 0x00,
2422 0x01, 0x00, 0x00, 0x00,
2423 0x01, 0x52, 0x53, 0x54
2425 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2426 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2427 if (IsSpdy4()) {
2428 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2429 } else {
2430 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2435 const char kDescription[] = "RST_STREAM frame with max stream ID";
2436 const unsigned char kV3FrameData[] = { // Also applies for V2.
2437 0x80, spdy_version_ch_, 0x00, 0x03,
2438 0x00, 0x00, 0x00, 0x08,
2439 0x7f, 0xff, 0xff, 0xff,
2440 0x00, 0x00, 0x00, 0x01,
2442 const unsigned char kV4FrameData[] = {
2443 0x00, 0x00, 0x04, 0x03,
2444 0x00, 0x7f, 0xff, 0xff,
2445 0xff, 0x00, 0x00, 0x00,
2446 0x01,
2448 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2449 RST_STREAM_PROTOCOL_ERROR,
2450 "");
2451 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2452 if (IsSpdy4()) {
2453 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2454 } else {
2455 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2460 const char kDescription[] = "RST_STREAM frame with max status code";
2461 const unsigned char kV3FrameData[] = { // Also applies for V2.
2462 0x80, spdy_version_ch_, 0x00, 0x03,
2463 0x00, 0x00, 0x00, 0x08,
2464 0x7f, 0xff, 0xff, 0xff,
2465 0x00, 0x00, 0x00, 0x06,
2467 const unsigned char kV4FrameData[] = {
2468 0x00, 0x00, 0x04, 0x03,
2469 0x00, 0x7f, 0xff, 0xff,
2470 0xff, 0x00, 0x00, 0x00,
2471 0x02,
2473 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2474 RST_STREAM_INTERNAL_ERROR,
2475 "");
2476 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2477 if (IsSpdy4()) {
2478 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2479 } else {
2480 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2485 TEST_P(SpdyFramerTest, CreateSettings) {
2486 SpdyFramer framer(spdy_version_);
2489 const char kDescription[] = "Network byte order SETTINGS frame";
2491 const unsigned char kV2FrameData[] = {
2492 0x80, spdy_version_ch_, 0x00, 0x04,
2493 0x00, 0x00, 0x00, 0x0c,
2494 0x00, 0x00, 0x00, 0x01,
2495 0x07, 0x00, 0x00, 0x01,
2496 0x0a, 0x0b, 0x0c, 0x0d,
2498 const unsigned char kV3FrameData[] = {
2499 0x80, spdy_version_ch_, 0x00, 0x04,
2500 0x00, 0x00, 0x00, 0x0c,
2501 0x00, 0x00, 0x00, 0x01,
2502 0x01, 0x00, 0x00, 0x07,
2503 0x0a, 0x0b, 0x0c, 0x0d,
2505 const unsigned char kV4FrameData[] = {
2506 0x00, 0x00, 0x06, 0x04,
2507 0x00, 0x00, 0x00, 0x00,
2508 0x00, 0x00, 0x04, 0x0a,
2509 0x0b, 0x0c, 0x0d,
2512 uint32 kValue = 0x0a0b0c0d;
2513 SpdySettingsIR settings_ir;
2515 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2516 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2517 SettingsMap settings;
2518 settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
2519 EXPECT_EQ(kFlags, settings[kId].first);
2520 EXPECT_EQ(kValue, settings[kId].second);
2521 settings_ir.AddSetting(kId,
2522 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2523 kFlags & SETTINGS_FLAG_PERSISTED,
2524 kValue);
2526 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2527 if (IsSpdy2()) {
2528 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2529 } else if (IsSpdy3()) {
2530 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2531 } else {
2532 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2537 const char kDescription[] = "Basic SETTINGS frame";
2539 const unsigned char kV2FrameData[] = {
2540 0x80, spdy_version_ch_, 0x00, 0x04,
2541 0x00, 0x00, 0x00, 0x24,
2542 0x00, 0x00, 0x00, 0x04,
2543 0x01, 0x00, 0x00, 0x00, // 1st Setting
2544 0x00, 0x00, 0x00, 0x05,
2545 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2546 0x00, 0x00, 0x00, 0x06,
2547 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2548 0x00, 0x00, 0x00, 0x07,
2549 0x04, 0x00, 0x00, 0x00, // 4th Setting
2550 0x00, 0x00, 0x00, 0x08,
2552 const unsigned char kV3FrameData[] = {
2553 0x80, spdy_version_ch_, 0x00, 0x04,
2554 0x00, 0x00, 0x00, 0x24,
2555 0x00, 0x00, 0x00, 0x04,
2556 0x00, 0x00, 0x00, 0x01, // 1st Setting
2557 0x00, 0x00, 0x00, 0x05,
2558 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2559 0x00, 0x00, 0x00, 0x06,
2560 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2561 0x00, 0x00, 0x00, 0x07,
2562 0x00, 0x00, 0x00, 0x04, // 4th Setting
2563 0x00, 0x00, 0x00, 0x08,
2565 // These end up seemingly out of order because of the way that our internal
2566 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2567 // the wire.
2568 const unsigned char kV4FrameData[] = {
2569 0x00, 0x00, 0x18, 0x04,
2570 0x00, 0x00, 0x00, 0x00,
2571 0x00, 0x00, 0x03, // 3rd Setting
2572 0x00, 0x00, 0x00, 0x07,
2573 0x00, 0x04, // 4th Setting
2574 0x00, 0x00, 0x00, 0x08,
2575 0x00, 0x01, // 1st Setting
2576 0x00, 0x00, 0x00, 0x05,
2577 0x00, 0x02, // 2nd Setting
2578 0x00, 0x00, 0x00, 0x06,
2581 SpdySettingsIR settings_ir;
2582 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2583 false, // persist
2584 false, // persisted
2586 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2587 false, // persist
2588 false, // persisted
2590 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2591 false, // persist
2592 false, // persisted
2594 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2595 false, // persist
2596 false, // persisted
2598 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2600 if (IsSpdy2()) {
2601 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2602 } else if (IsSpdy3()) {
2603 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2604 } else {
2605 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2610 const char kDescription[] = "Empty SETTINGS frame";
2612 const unsigned char kV3FrameData[] = { // Also applies for V2.
2613 0x80, spdy_version_ch_, 0x00, 0x04,
2614 0x00, 0x00, 0x00, 0x04,
2615 0x00, 0x00, 0x00, 0x00,
2617 const unsigned char kV4FrameData[] = {
2618 0x00, 0x00, 0x00, 0x04,
2619 0x00, 0x00, 0x00, 0x00,
2620 0x00,
2622 SpdySettingsIR settings_ir;
2623 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2624 if (IsSpdy4()) {
2625 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2626 } else {
2627 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2632 TEST_P(SpdyFramerTest, CreatePingFrame) {
2633 SpdyFramer framer(spdy_version_);
2636 const char kDescription[] = "PING frame";
2637 const unsigned char kV3FrameData[] = { // Also applies for V2.
2638 0x80, spdy_version_ch_, 0x00, 0x06,
2639 0x00, 0x00, 0x00, 0x04,
2640 0x12, 0x34, 0x56, 0x78,
2642 const unsigned char kV4FrameData[] = {
2643 0x00, 0x00, 0x08, 0x06,
2644 0x00, 0x00, 0x00, 0x00,
2645 0x00, 0x12, 0x34, 0x56,
2646 0x78, 0x9a, 0xbc, 0xde,
2647 0xff,
2649 const unsigned char kV4FrameDataWithAck[] = {
2650 0x00, 0x00, 0x08, 0x06,
2651 0x01, 0x00, 0x00, 0x00,
2652 0x00, 0x12, 0x34, 0x56,
2653 0x78, 0x9a, 0xbc, 0xde,
2654 0xff,
2656 scoped_ptr<SpdyFrame> frame;
2657 if (IsSpdy4()) {
2658 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2659 SpdyPingIR ping_ir(kPingId);
2660 // Tests SpdyPingIR when the ping is not an ack.
2661 ASSERT_FALSE(ping_ir.is_ack());
2662 frame.reset(framer.SerializePing(ping_ir));
2663 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2665 // Tests SpdyPingIR when the ping is an ack.
2666 ping_ir.set_is_ack(true);
2667 frame.reset(framer.SerializePing(ping_ir));
2668 CompareFrame(kDescription, *frame,
2669 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2671 } else {
2672 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2673 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2678 TEST_P(SpdyFramerTest, CreateGoAway) {
2679 SpdyFramer framer(spdy_version_);
2682 const char kDescription[] = "GOAWAY frame";
2683 const unsigned char kV2FrameData[] = {
2684 0x80, spdy_version_ch_, 0x00, 0x07,
2685 0x00, 0x00, 0x00, 0x04,
2686 0x00, 0x00, 0x00, 0x00, // Stream Id
2688 const unsigned char kV3FrameData[] = {
2689 0x80, spdy_version_ch_, 0x00, 0x07,
2690 0x00, 0x00, 0x00, 0x08,
2691 0x00, 0x00, 0x00, 0x00, // Stream Id
2692 0x00, 0x00, 0x00, 0x00, // Status
2694 const unsigned char kV4FrameData[] = {
2695 0x00, 0x00, 0x0a, 0x07,
2696 0x00, 0x00, 0x00, 0x00,
2697 0x00, 0x00, 0x00, 0x00, // Stream id
2698 0x00, 0x00, 0x00, 0x00, // Status
2699 0x00, 0x47, 0x41, // Opaque Description
2701 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2702 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2703 if (IsSpdy2()) {
2704 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2705 } else if (IsSpdy3()) {
2706 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2707 } else {
2708 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2713 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2714 const unsigned char kV2FrameData[] = {
2715 0x80, spdy_version_ch_, 0x00, 0x07,
2716 0x00, 0x00, 0x00, 0x04,
2717 0x7f, 0xff, 0xff, 0xff, // Stream Id
2719 const unsigned char kV3FrameData[] = {
2720 0x80, spdy_version_ch_, 0x00, 0x07,
2721 0x00, 0x00, 0x00, 0x08,
2722 0x7f, 0xff, 0xff, 0xff, // Stream Id
2723 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2725 const unsigned char kV4FrameData[] = {
2726 0x00, 0x00, 0x0a, 0x07,
2727 0x00, 0x00, 0x00, 0x00,
2728 0x00, 0x7f, 0xff, 0xff, // Stream Id
2729 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2730 0x02, 0x47, 0x41, // Opaque Description
2732 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2733 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2734 if (IsSpdy2()) {
2735 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2736 } else if (IsSpdy3()) {
2737 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2738 } else {
2739 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2744 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2745 SpdyFramer framer(spdy_version_);
2746 framer.set_enable_compression(false);
2749 const char kDescription[] = "HEADERS frame, no FIN";
2751 const unsigned char kV2FrameData[] = {
2752 0x80, spdy_version_ch_, 0x00, 0x08,
2753 0x00, 0x00, 0x00, 0x1C,
2754 0x00, 0x00, 0x00, 0x01,
2755 0x00, 0x00, 0x00, 0x02,
2756 0x00, 0x03, 'b', 'a',
2757 'r', 0x00, 0x03, 'f',
2758 'o', 'o', 0x00, 0x03,
2759 'f', 'o', 'o', 0x00,
2760 0x03, 'b', 'a', 'r'
2762 const unsigned char kV3FrameData[] = {
2763 0x80, spdy_version_ch_, 0x00, 0x08,
2764 0x00, 0x00, 0x00, 0x24,
2765 0x00, 0x00, 0x00, 0x01,
2766 0x00, 0x00, 0x00, 0x02,
2767 0x00, 0x00, 0x00, 0x03,
2768 'b', 'a', 'r', 0x00,
2769 0x00, 0x00, 0x03, 'f',
2770 'o', 'o', 0x00, 0x00,
2771 0x00, 0x03, 'f', 'o',
2772 'o', 0x00, 0x00, 0x00,
2773 0x03, 'b', 'a', 'r'
2775 const unsigned char kV4FrameData[] = {
2776 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2777 0x04, 0x00, 0x00, 0x00, // Stream 1
2778 0x01, 0x00, 0x03, 0x62, // @.ba
2779 0x61, 0x72, 0x03, 0x66, // r.fo
2780 0x6f, 0x6f, 0x00, 0x03, // o@.f
2781 0x66, 0x6f, 0x6f, 0x03, // oo.b
2782 0x62, 0x61, 0x72, // ar
2784 SpdyHeadersIR headers_ir(1);
2785 headers_ir.SetHeader("bar", "foo");
2786 headers_ir.SetHeader("foo", "bar");
2787 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2788 if (IsSpdy2()) {
2789 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2790 } else if (IsSpdy3()) {
2791 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2792 } else {
2793 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2798 const char kDescription[] =
2799 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2801 const unsigned char kV2FrameData[] = {
2802 0x80, spdy_version_ch_, 0x00, 0x08,
2803 0x01, 0x00, 0x00, 0x19,
2804 0x7f, 0xff, 0xff, 0xff,
2805 0x00, 0x00, 0x00, 0x02,
2806 0x00, 0x00, 0x00, 0x03,
2807 'f', 'o', 'o', 0x00,
2808 0x03, 'f', 'o', 'o',
2809 0x00, 0x03, 'b', 'a',
2812 const unsigned char kV3FrameData[] = {
2813 0x80, spdy_version_ch_, 0x00, 0x08,
2814 0x01, 0x00, 0x00, 0x21,
2815 0x7f, 0xff, 0xff, 0xff,
2816 0x00, 0x00, 0x00, 0x02,
2817 0x00, 0x00, 0x00, 0x00,
2818 0x00, 0x00, 0x00, 0x03,
2819 'f', 'o', 'o', 0x00,
2820 0x00, 0x00, 0x03, 'f',
2821 'o', 'o', 0x00, 0x00,
2822 0x00, 0x03, 'b', 'a',
2825 const unsigned char kV4FrameData[] = {
2826 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2827 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2828 0xff, 0x00, 0x00, 0x03, // @..
2829 0x66, 0x6f, 0x6f, 0x00, // foo@
2830 0x03, 0x66, 0x6f, 0x6f, // .foo
2831 0x03, 0x62, 0x61, 0x72, // .bar
2833 SpdyHeadersIR headers_ir(0x7fffffff);
2834 headers_ir.set_fin(true);
2835 headers_ir.SetHeader("", "foo");
2836 headers_ir.SetHeader("foo", "bar");
2837 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2838 if (IsSpdy2()) {
2839 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2840 } else if (IsSpdy3()) {
2841 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2842 } else {
2843 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2848 const char kDescription[] =
2849 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2851 const unsigned char kV2FrameData[] = {
2852 0x80, spdy_version_ch_, 0x00, 0x08,
2853 0x01, 0x00, 0x00, 0x19,
2854 0x7f, 0xff, 0xff, 0xff,
2855 0x00, 0x00, 0x00, 0x02,
2856 0x00, 0x03, 'b', 'a',
2857 'r', 0x00, 0x03, 'f',
2858 'o', 'o', 0x00, 0x03,
2859 'f', 'o', 'o', 0x00,
2860 0x00
2862 const unsigned char kV3FrameData[] = {
2863 0x80, spdy_version_ch_, 0x00, 0x08,
2864 0x01, 0x00, 0x00, 0x21,
2865 0x7f, 0xff, 0xff, 0xff,
2866 0x00, 0x00, 0x00, 0x02,
2867 0x00, 0x00, 0x00, 0x03,
2868 'b', 'a', 'r', 0x00,
2869 0x00, 0x00, 0x03, 'f',
2870 'o', 'o', 0x00, 0x00,
2871 0x00, 0x03, 'f', 'o',
2872 'o', 0x00, 0x00, 0x00,
2873 0x00
2875 const unsigned char kV4FrameData[] = {
2876 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2877 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2878 0xff, 0x00, 0x03, 0x62, // @.b
2879 0x61, 0x72, 0x03, 0x66, // ar.f
2880 0x6f, 0x6f, 0x00, 0x03, // oo@.
2881 0x66, 0x6f, 0x6f, 0x00, // foo.
2883 SpdyHeadersIR headers_ir(0x7fffffff);
2884 headers_ir.set_fin(true);
2885 headers_ir.SetHeader("bar", "foo");
2886 headers_ir.SetHeader("foo", "");
2887 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2888 if (IsSpdy2()) {
2889 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2890 } else if (IsSpdy3()) {
2891 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2892 } else {
2893 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2898 const char kDescription[] =
2899 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2901 const unsigned char kV4FrameData[] = {
2902 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2903 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2904 0xff, 0x00, 0x00, 0x00, // parent stream
2905 0x00, 0xdb, // weight
2906 0x00, 0x03, 0x62, 0x61, // @.ba
2907 0x72, 0x03, 0x66, 0x6f, // r.fo
2908 0x6f, 0x00, 0x03, 0x66, // o@.f
2909 0x6f, 0x6f, 0x00, // oo.
2911 SpdyHeadersIR headers_ir(0x7fffffff);
2912 headers_ir.set_fin(true);
2913 headers_ir.set_priority(1);
2914 headers_ir.set_has_priority(true);
2915 headers_ir.SetHeader("bar", "foo");
2916 headers_ir.SetHeader("foo", "");
2917 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2918 if (IsSpdy2() || IsSpdy3()) {
2919 // HEADERS with priority not supported.
2920 } else {
2921 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2926 const char kDescription[] =
2927 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2929 const unsigned char kV4FrameData[] = {
2930 0x00, 0x00, 0x15, 0x01, // Headers
2931 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2932 // 0x7fffffff
2933 0xff, 0x05, 0x00, 0x00, // Pad length field
2934 0x03, 0x66, 0x6f, 0x6f, // .foo
2935 0x00, 0x03, 0x66, 0x6f, // @.fo
2936 0x6f, 0x03, 0x62, 0x61, // o.ba
2937 0x72, // r
2938 // Padding payload
2939 0x00, 0x00, 0x00, 0x00, 0x00,
2941 SpdyHeadersIR headers_ir(0x7fffffff);
2942 headers_ir.set_fin(true);
2943 headers_ir.SetHeader("", "foo");
2944 headers_ir.SetHeader("foo", "bar");
2945 headers_ir.set_padding_len(6);
2946 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2947 if (IsSpdy2() || IsSpdy3()) {
2948 // Padding is not supported.
2949 } else {
2950 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2955 // TODO(phajdan.jr): Clean up after we no longer need
2956 // to workaround http://crbug.com/139744.
2957 #if !defined(USE_SYSTEM_ZLIB)
2958 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2959 SpdyFramer framer(spdy_version_);
2960 framer.set_enable_compression(true);
2963 const char kDescription[] = "HEADERS frame, no FIN";
2965 const unsigned char kV2FrameData[] = {
2966 0x80, spdy_version_ch_, 0x00, 0x08,
2967 0x00, 0x00, 0x00, 0x32,
2968 0x00, 0x00, 0x00, 0x01,
2969 0x00, 0x00, 0x38, 0xea,
2970 0xdf, 0xa2, 0x51, 0xb2,
2971 0x62, 0x60, 0x62, 0x60,
2972 0x4e, 0x4a, 0x2c, 0x62,
2973 0x60, 0x06, 0x08, 0xa0,
2974 0xb4, 0xfc, 0x7c, 0x80,
2975 0x00, 0x62, 0x60, 0x4e,
2976 0xcb, 0xcf, 0x67, 0x60,
2977 0x06, 0x08, 0xa0, 0xa4,
2978 0xc4, 0x22, 0x80, 0x00,
2979 0x02, 0x00, 0x00, 0x00,
2980 0xff, 0xff,
2982 const unsigned char kV3FrameData[] = {
2983 0x80, spdy_version_ch_, 0x00, 0x08,
2984 0x00, 0x00, 0x00, 0x31,
2985 0x00, 0x00, 0x00, 0x01,
2986 0x38, 0xea, 0xe3, 0xc6,
2987 0xa7, 0xc2, 0x02, 0xe5,
2988 0x0e, 0x50, 0xc2, 0x4b,
2989 0x4a, 0x04, 0xe5, 0x0b,
2990 0x66, 0x80, 0x00, 0x4a,
2991 0xcb, 0xcf, 0x07, 0x08,
2992 0x20, 0x10, 0x95, 0x96,
2993 0x9f, 0x0f, 0xa2, 0x00,
2994 0x02, 0x28, 0x29, 0xb1,
2995 0x08, 0x20, 0x80, 0x00,
2996 0x00, 0x00, 0x00, 0xff,
2997 0xff,
2999 const unsigned char kV2SIMDFrameData[] = {
3000 0x80, spdy_version_ch_, 0x00, 0x08,
3001 0x00, 0x00, 0x00, 0x2f,
3002 0x00, 0x00, 0x00, 0x01,
3003 0x00, 0x00, 0x38, 0xea,
3004 0xdf, 0xa2, 0x51, 0xb2,
3005 0x62, 0x60, 0x62, 0x60,
3006 0x4e, 0x4a, 0x2c, 0x62,
3007 0x60, 0x06, 0x08, 0xa0,
3008 0xb4, 0xfc, 0x7c, 0x80,
3009 0x00, 0x62, 0x60, 0x06,
3010 0x13, 0x00, 0x01, 0x94,
3011 0x94, 0x58, 0x04, 0x10,
3012 0x40, 0x00, 0x00, 0x00,
3013 0x00, 0xff, 0xff,
3015 const unsigned char kV3SIMDFrameData[] = {
3016 0x80, spdy_version_ch_, 0x00, 0x08,
3017 0x00, 0x00, 0x00, 0x2c,
3018 0x00, 0x00, 0x00, 0x01,
3019 0x38, 0xea, 0xe3, 0xc6,
3020 0xa7, 0xc2, 0x02, 0xe5,
3021 0x0e, 0x50, 0xc2, 0x4b,
3022 0x4a, 0x04, 0xe5, 0x0b,
3023 0x66, 0x80, 0x00, 0x4a,
3024 0xcb, 0xcf, 0x07, 0x08,
3025 0x20, 0x24, 0x0a, 0x20,
3026 0x80, 0x92, 0x12, 0x8b,
3027 0x00, 0x02, 0x08, 0x00,
3028 0x00, 0x00, 0xff, 0xff,
3031 SpdyHeadersIR headers_ir(1);
3032 headers_ir.SetHeader("bar", "foo");
3033 headers_ir.SetHeader("foo", "bar");
3034 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3035 const unsigned char* frame_data =
3036 reinterpret_cast<const unsigned char*>(frame->data());
3037 if (IsSpdy2()) {
3038 // Try comparing with SIMD version, if that fails, do a failing check
3039 // with pretty printing against non-SIMD version
3040 if (memcmp(frame_data,
3041 kV2SIMDFrameData,
3042 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3043 CompareCharArraysWithHexError(kDescription,
3044 frame_data,
3045 frame->size(),
3046 kV2FrameData,
3047 arraysize(kV2FrameData));
3049 } else if (IsSpdy3()) {
3050 if (memcmp(frame_data,
3051 kV3SIMDFrameData,
3052 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3053 CompareCharArraysWithHexError(kDescription,
3054 frame_data,
3055 frame->size(),
3056 kV3FrameData,
3057 arraysize(kV3FrameData));
3059 } else {
3060 // Deflate compression doesn't apply to HPACK.
3064 #endif // !defined(USE_SYSTEM_ZLIB)
3066 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3067 SpdyFramer framer(spdy_version_);
3070 const char kDescription[] = "WINDOW_UPDATE frame";
3071 const unsigned char kV3FrameData[] = { // Also applies for V2.
3072 0x80, spdy_version_ch_, 0x00, 0x09,
3073 0x00, 0x00, 0x00, 0x08,
3074 0x00, 0x00, 0x00, 0x01,
3075 0x00, 0x00, 0x00, 0x01,
3077 const unsigned char kV4FrameData[] = {
3078 0x00, 0x00, 0x04, 0x08,
3079 0x00, 0x00, 0x00, 0x00,
3080 0x01, 0x00, 0x00, 0x00,
3081 0x01,
3083 scoped_ptr<SpdyFrame> frame(
3084 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3085 if (IsSpdy4()) {
3086 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3087 } else {
3088 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3093 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3094 const unsigned char kV3FrameData[] = { // Also applies for V2.
3095 0x80, spdy_version_ch_, 0x00, 0x09,
3096 0x00, 0x00, 0x00, 0x08,
3097 0x7f, 0xff, 0xff, 0xff,
3098 0x00, 0x00, 0x00, 0x01,
3100 const unsigned char kV4FrameData[] = {
3101 0x00, 0x00, 0x04, 0x08,
3102 0x00, 0x7f, 0xff, 0xff,
3103 0xff, 0x00, 0x00, 0x00,
3104 0x01,
3106 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3107 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3108 if (IsSpdy4()) {
3109 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3110 } else {
3111 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3116 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3117 const unsigned char kV3FrameData[] = { // Also applies for V2.
3118 0x80, spdy_version_ch_, 0x00, 0x09,
3119 0x00, 0x00, 0x00, 0x08,
3120 0x00, 0x00, 0x00, 0x01,
3121 0x7f, 0xff, 0xff, 0xff,
3123 const unsigned char kV4FrameData[] = {
3124 0x00, 0x00, 0x04, 0x08,
3125 0x00, 0x00, 0x00, 0x00,
3126 0x01, 0x7f, 0xff, 0xff,
3127 0xff,
3129 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3130 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3131 if (IsSpdy4()) {
3132 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3133 } else {
3134 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3139 TEST_P(SpdyFramerTest, SerializeBlocked) {
3140 if (spdy_version_ <= SPDY3) {
3141 return;
3144 SpdyFramer framer(spdy_version_);
3146 const char kDescription[] = "BLOCKED frame";
3147 const unsigned char kType = static_cast<unsigned char>(
3148 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3149 const unsigned char kFrameData[] = {
3150 0x00, 0x00, 0x00, kType, 0x00,
3151 0x00, 0x00, 0x00, 0x00,
3153 SpdyBlockedIR blocked_ir(0);
3154 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3155 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3158 TEST_P(SpdyFramerTest, CreateBlocked) {
3159 if (spdy_version_ <= SPDY3) {
3160 return;
3163 SpdyFramer framer(spdy_version_);
3165 const char kDescription[] = "BLOCKED frame";
3166 const SpdyStreamId kStreamId = 3;
3168 scoped_ptr<SpdySerializedFrame> frame_serialized(
3169 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3170 SpdyBlockedIR blocked_ir(kStreamId);
3171 scoped_ptr<SpdySerializedFrame> frame_created(
3172 framer.SerializeFrame(blocked_ir));
3174 CompareFrames(kDescription, *frame_serialized, *frame_created);
3177 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3178 if (spdy_version_ <= SPDY3) {
3179 return;
3183 // Test framing PUSH_PROMISE without padding.
3184 SpdyFramer framer(spdy_version_);
3185 framer.set_enable_compression(false);
3186 const char kDescription[] = "PUSH_PROMISE frame without padding";
3188 const unsigned char kFrameData[] = {
3189 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3190 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3191 0x2a, 0x00, 0x00, 0x00, // Stream 42
3192 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3193 0x61, 0x72, 0x03, 0x66, // ar.f
3194 0x6f, 0x6f, 0x00, 0x03, // oo@.
3195 0x66, 0x6f, 0x6f, 0x03, // foo.
3196 0x62, 0x61, 0x72, // bar
3199 SpdyPushPromiseIR push_promise(42, 57);
3200 push_promise.SetHeader("bar", "foo");
3201 push_promise.SetHeader("foo", "bar");
3202 scoped_ptr<SpdySerializedFrame> frame(
3203 framer.SerializePushPromise(push_promise));
3204 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3208 // Test framing PUSH_PROMISE with one byte of padding.
3209 SpdyFramer framer(spdy_version_);
3210 framer.set_enable_compression(false);
3211 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3213 const unsigned char kFrameData[] = {
3214 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3215 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3216 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3217 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3218 0x62, 0x61, 0x72, 0x03, // bar.
3219 0x66, 0x6f, 0x6f, 0x00, // foo@
3220 0x03, 0x66, 0x6f, 0x6f, // .foo
3221 0x03, 0x62, 0x61, 0x72, // .bar
3224 SpdyPushPromiseIR push_promise(42, 57);
3225 push_promise.set_padding_len(1);
3226 push_promise.SetHeader("bar", "foo");
3227 push_promise.SetHeader("foo", "bar");
3228 scoped_ptr<SpdySerializedFrame> frame(
3229 framer.SerializePushPromise(push_promise));
3230 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3234 // Test framing PUSH_PROMISE with 177 bytes of padding.
3235 SpdyFramer framer(spdy_version_);
3236 framer.set_enable_compression(false);
3237 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3239 const unsigned char kFrameData[] = {
3240 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3241 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3242 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3243 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3244 0x62, 0x61, 0x72, 0x03, // bar.
3245 0x66, 0x6f, 0x6f, 0x00, // foo@
3246 0x03, 0x66, 0x6f, 0x6f, // .foo
3247 0x03, 0x62, 0x61, 0x72, // .bar
3248 // Padding of 176 0x00(s).
3249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
3266 SpdyPushPromiseIR push_promise(42, 57);
3267 push_promise.set_padding_len(177);
3268 push_promise.SetHeader("bar", "foo");
3269 push_promise.SetHeader("foo", "bar");
3270 scoped_ptr<SpdySerializedFrame> frame(
3271 framer.SerializePushPromise(push_promise));
3272 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3276 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3277 if (spdy_version_ <= SPDY3) {
3278 return;
3281 SpdyFramer framer(spdy_version_);
3282 framer.set_enable_compression(false);
3283 const char kDescription[] = "CONTINUATION frame";
3285 const unsigned char kFrameData[] = {
3286 0x00, 0x00, 0x12, 0x09, 0x00, // CONTINUATION
3287 0x00, 0x00, 0x00, 0x2a, // Stream 42
3288 0x00, 0x03, 0x62, 0x61, // @.ba
3289 0x72, 0x03, 0x66, 0x6f, // r.fo
3290 0x6f, 0x00, 0x03, 0x66, // o@.f
3291 0x6f, 0x6f, 0x03, 0x62, // oo.b
3292 0x61, 0x72, // ar
3295 SpdyContinuationIR continuation(42);
3296 continuation.SetHeader("bar", "foo");
3297 continuation.SetHeader("foo", "bar");
3298 scoped_ptr<SpdySerializedFrame> frame(
3299 framer.SerializeContinuation(continuation));
3300 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3303 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3304 if (spdy_version_ <= SPDY3) {
3305 return;
3309 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3310 // padding, cannot hold all the data payload, which is overflowed to the
3311 // consecutive CONTINUATION frame.
3312 SpdyFramer framer(spdy_version_);
3313 framer.set_enable_compression(false);
3314 const char kDescription[] =
3315 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3317 const unsigned char kPartialPushPromiseFrameData[] = {
3318 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3319 0x08, 0x00, 0x00, 0x00, // PADDED
3320 0x2a, 0x00, 0x00, 0x00, // Stream 42
3321 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3322 0x78, 0x78, 0x78, 0x7f, // xxx.
3323 0x81, 0x07, 0x78, 0x78, // ..xx
3324 0x78, 0x78, 0x78, 0x78, // xxxx
3325 0x78, 0x78, 0x78, 0x78, // xxxx
3326 0x78, 0x78, 0x78, 0x78, // xxxx
3327 0x78, 0x78, 0x78, 0x78, // xxxx
3328 0x78, 0x78, 0x78, 0x78, // xxxx
3329 0x78, 0x78, 0x78, 0x78, // xxxx
3330 0x78, 0x78, 0x78, 0x78, // xxxx
3331 0x78, 0x78, 0x78, 0x78, // xxxx
3332 0x78, 0x78, 0x78, 0x78, // xxxx
3333 0x78, 0x78, 0x78, 0x78, // xxxx
3334 0x78, 0x78, 0x78, 0x78, // xxxx
3335 0x78, 0x78, 0x78, 0x78, // xxxx
3336 0x78, 0x78, 0x78, 0x78, // xxxx
3337 0x78, 0x78, 0x78, 0x78, // xxxx
3338 0x78, 0x78, 0x78, 0x78, // xxxx
3339 0x78, 0x78, 0x78, 0x78, // xxxx
3340 0x78, 0x78, 0x78, 0x78, // xxxx
3341 0x78, 0x78, 0x78, 0x78, // xxxx
3342 0x78, 0x78, 0x78, 0x78, // xxxx
3343 0x78, 0x78, 0x78, 0x78, // xxxx
3344 0x78, 0x78, // xx
3347 const unsigned char kContinuationFrameData[] = {
3348 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3349 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3350 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
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,
3358 SpdyPushPromiseIR push_promise(42, 57);
3359 push_promise.set_padding_len(1);
3360 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3361 push_promise.SetHeader("xxx", big_value);
3362 scoped_ptr<SpdySerializedFrame> frame(
3363 framer.SerializePushPromise(push_promise));
3365 // The entire frame should look like below:
3366 // Name Length in Byte
3367 // ------------------------------------------- Begin of PUSH_PROMISE frame
3368 // PUSH_PROMISE header 9
3369 // Pad length field 1
3370 // Promised stream 4
3371 // Length field of key 2
3372 // Content of key 3
3373 // Length field of value 3
3374 // Part of big_value 16361
3375 // ------------------------------------------- Begin of CONTINUATION frame
3376 // CONTINUATION header 9
3377 // Remaining of big_value 22
3378 // ------------------------------------------- End
3380 // Length of everything listed above except big_value.
3381 int len_non_data_payload = 31;
3382 EXPECT_EQ(
3383 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3384 frame->size());
3386 // Partially compare the PUSH_PROMISE frame against the template.
3387 const unsigned char* frame_data =
3388 reinterpret_cast<const unsigned char*>(frame->data());
3389 CompareCharArraysWithHexError(kDescription,
3390 frame_data,
3391 arraysize(kPartialPushPromiseFrameData),
3392 kPartialPushPromiseFrameData,
3393 arraysize(kPartialPushPromiseFrameData));
3395 // Compare the CONTINUATION frame against the template.
3396 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3397 CompareCharArraysWithHexError(kDescription,
3398 frame_data,
3399 arraysize(kContinuationFrameData),
3400 kContinuationFrameData,
3401 arraysize(kContinuationFrameData));
3405 TEST_P(SpdyFramerTest, CreateAltSvc) {
3406 if (spdy_version_ <= SPDY3) {
3407 return;
3410 SpdyFramer framer(spdy_version_);
3412 const char kDescription[] = "ALTSVC frame";
3413 const unsigned char kType = static_cast<unsigned char>(
3414 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3415 const unsigned char kFrameData[] = {
3416 0x00, 0x00, 0x17, kType, 0x00,
3417 0x00, 0x00, 0x00, 0x03,
3418 0x00, 0x00, 0x00, 0x05,
3419 0x01, 0xbb, 0x00, 0x04, // Port = 443
3420 'p', 'i', 'd', '1', // Protocol-ID
3421 0x04, 'h', 'o', 's',
3422 't', 'o', 'r', 'i',
3423 'g', 'i', 'n',
3425 SpdyAltSvcIR altsvc_ir(3);
3426 altsvc_ir.set_max_age(5);
3427 altsvc_ir.set_port(443);
3428 altsvc_ir.set_protocol_id("pid1");
3429 altsvc_ir.set_host("host");
3430 altsvc_ir.set_origin("origin");
3431 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3432 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3435 TEST_P(SpdyFramerTest, CreatePriority) {
3436 if (spdy_version_ <= SPDY3) {
3437 return;
3440 SpdyFramer framer(spdy_version_);
3442 const char kDescription[] = "PRIORITY frame";
3443 const unsigned char kType = static_cast<unsigned char>(
3444 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3445 const unsigned char kFrameData[] = {
3446 0x00, 0x00, 0x05, kType, 0x00,
3447 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3448 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3449 0x10, // Weight = 16
3451 SpdyPriorityIR priority_ir(2, 1, 16, true);
3452 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3453 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3456 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3457 if (spdy_version_ > SPDY3) {
3458 // SYN_STREAM not supported in SPDY>3
3459 return;
3461 SpdyFramer framer(spdy_version_);
3462 SpdySynStreamIR syn_stream(1);
3463 syn_stream.set_priority(1);
3464 syn_stream.SetHeader("aa", "vv");
3465 syn_stream.SetHeader("bb", "ww");
3466 SpdyHeaderBlock headers = syn_stream.name_value_block();
3467 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3468 EXPECT_TRUE(control_frame.get() != NULL);
3469 TestSpdyVisitor visitor(spdy_version_);
3470 visitor.use_compression_ = true;
3471 visitor.SimulateInFramer(
3472 reinterpret_cast<unsigned char*>(control_frame->data()),
3473 control_frame->size());
3474 EXPECT_EQ(1, visitor.syn_frame_count_);
3475 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3478 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3479 if (spdy_version_ > SPDY3) {
3480 return;
3482 SpdyFramer framer(spdy_version_);
3483 SpdySynReplyIR syn_reply(1);
3484 syn_reply.SetHeader("alpha", "beta");
3485 syn_reply.SetHeader("gamma", "delta");
3486 SpdyHeaderBlock headers = syn_reply.name_value_block();
3487 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3488 EXPECT_TRUE(control_frame.get() != NULL);
3489 TestSpdyVisitor visitor(spdy_version_);
3490 visitor.use_compression_ = true;
3491 visitor.SimulateInFramer(
3492 reinterpret_cast<unsigned char*>(control_frame->data()),
3493 control_frame->size());
3494 if (IsSpdy4()) {
3495 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3496 EXPECT_EQ(1, visitor.headers_frame_count_);
3497 } else {
3498 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3499 EXPECT_EQ(0, visitor.headers_frame_count_);
3501 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3504 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3505 SpdyFramer framer(spdy_version_);
3506 SpdyHeadersIR headers_ir(1);
3507 headers_ir.SetHeader("alpha", "beta");
3508 headers_ir.SetHeader("gamma", "delta");
3509 SpdyHeaderBlock headers = headers_ir.name_value_block();
3510 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3511 EXPECT_TRUE(control_frame.get() != NULL);
3512 TestSpdyVisitor visitor(spdy_version_);
3513 visitor.use_compression_ = true;
3514 visitor.SimulateInFramer(
3515 reinterpret_cast<unsigned char*>(control_frame->data()),
3516 control_frame->size());
3517 EXPECT_EQ(1, visitor.headers_frame_count_);
3518 // control_frame_header_data_count_ depends on the random sequence
3519 // produced by rand(), so adding, removing or running single tests
3520 // alters this value. The best we can do is assert that it happens
3521 // at least twice.
3522 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3523 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3524 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3525 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3528 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3529 SpdyFramer framer(spdy_version_);
3530 SpdyHeadersIR headers_ir(1);
3531 headers_ir.set_fin(true);
3532 headers_ir.SetHeader("alpha", "beta");
3533 headers_ir.SetHeader("gamma", "delta");
3534 SpdyHeaderBlock headers = headers_ir.name_value_block();
3535 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3536 EXPECT_TRUE(control_frame.get() != NULL);
3537 TestSpdyVisitor visitor(spdy_version_);
3538 visitor.use_compression_ = true;
3539 visitor.SimulateInFramer(
3540 reinterpret_cast<unsigned char*>(control_frame->data()),
3541 control_frame->size());
3542 EXPECT_EQ(1, visitor.headers_frame_count_);
3543 // control_frame_header_data_count_ depends on the random sequence
3544 // produced by rand(), so adding, removing or running single tests
3545 // alters this value. The best we can do is assert that it happens
3546 // at least twice.
3547 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3548 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3549 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3550 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3553 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3554 if (spdy_version_ > SPDY3) {
3555 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3556 return;
3558 // First find the size of the header value in order to just reach the control
3559 // frame max size.
3560 SpdyFramer framer(spdy_version_);
3561 framer.set_enable_compression(false);
3562 SpdySynStreamIR syn_stream(1);
3563 syn_stream.set_priority(1);
3564 syn_stream.SetHeader("aa", "");
3565 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3566 const size_t kBigValueSize =
3567 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3569 // Create a frame at exactly that size.
3570 string big_value(kBigValueSize, 'x');
3571 syn_stream.SetHeader("aa", big_value);
3572 control_frame.reset(framer.SerializeSynStream(syn_stream));
3573 EXPECT_TRUE(control_frame.get() != NULL);
3574 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3575 control_frame->size());
3577 TestSpdyVisitor visitor(spdy_version_);
3578 visitor.SimulateInFramer(
3579 reinterpret_cast<unsigned char*>(control_frame->data()),
3580 control_frame->size());
3581 EXPECT_TRUE(visitor.header_buffer_valid_);
3582 EXPECT_EQ(0, visitor.error_count_);
3583 EXPECT_EQ(1, visitor.syn_frame_count_);
3584 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3585 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3586 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3589 // This test is disabled because Chromium is willing to accept control frames up
3590 // to the maximum size allowed by the specification, and SpdyFrameBuilder is not
3591 // capable of building larger frames.
3592 TEST_P(SpdyFramerTest, DISABLED_ControlFrameTooLarge) {
3593 if (spdy_version_ > SPDY3) {
3594 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3595 return;
3597 // First find the size of the header value in order to just reach the control
3598 // frame max size.
3599 SpdyFramer framer(spdy_version_);
3600 framer.set_enable_compression(false);
3601 SpdySynStreamIR syn_stream(1);
3602 syn_stream.SetHeader("aa", "");
3603 syn_stream.set_priority(1);
3604 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3605 const size_t kBigValueSize =
3606 SpdyConstants::GetFrameMaximumSize(spdy_version_) -
3607 control_frame->size() + 1;
3609 // Create a frame at exatly that size.
3610 string big_value(kBigValueSize, 'x');
3611 syn_stream.SetHeader("aa", big_value);
3612 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3613 // neither support that in Chromium, nor do we use the same DFATAL (see
3614 // SpdyFrameBuilder::WriteFramePrefix()).
3615 control_frame.reset(framer.SerializeSynStream(syn_stream));
3617 EXPECT_TRUE(control_frame.get() != NULL);
3618 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_) + 1,
3619 control_frame->size());
3621 TestSpdyVisitor visitor(spdy_version_);
3622 visitor.SimulateInFramer(
3623 reinterpret_cast<unsigned char*>(control_frame->data()),
3624 control_frame->size());
3625 EXPECT_FALSE(visitor.header_buffer_valid_);
3626 EXPECT_EQ(1, visitor.error_count_);
3627 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3628 visitor.framer_.error_code())
3629 << SpdyFramer::ErrorCodeToString(framer.error_code());
3630 EXPECT_EQ(0, visitor.syn_frame_count_);
3631 EXPECT_EQ(0u, visitor.header_buffer_length_);
3634 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3635 if (spdy_version_ <= SPDY3) {
3636 return;
3638 SpdyFramer framer(spdy_version_);
3639 framer.set_enable_compression(false);
3640 SpdyHeadersIR headers(1);
3641 headers.set_padding_len(256);
3643 // Exact payload length will change with HPACK, but this should be long
3644 // enough to cause an overflow.
3645 const size_t kBigValueSize = kControlFrameSizeLimit;
3646 string big_value(kBigValueSize, 'x');
3647 headers.SetHeader("aa", big_value);
3648 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3649 EXPECT_TRUE(control_frame.get() != NULL);
3650 EXPECT_GT(control_frame->size(),
3651 TestSpdyVisitor::sent_control_frame_max_size());
3653 TestSpdyVisitor visitor(spdy_version_);
3654 visitor.SimulateInFramer(
3655 reinterpret_cast<unsigned char*>(control_frame->data()),
3656 control_frame->size());
3657 EXPECT_TRUE(visitor.header_buffer_valid_);
3658 EXPECT_EQ(0, visitor.error_count_);
3659 EXPECT_EQ(1, visitor.headers_frame_count_);
3660 EXPECT_EQ(16, visitor.continuation_count_);
3661 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3664 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3665 if (spdy_version_ <= SPDY3) {
3666 return;
3668 SpdyFramer framer(spdy_version_);
3669 framer.set_enable_compression(false);
3670 SpdyPushPromiseIR push_promise(1, 2);
3671 push_promise.set_padding_len(256);
3673 // Exact payload length will change with HPACK, but this should be long
3674 // enough to cause an overflow.
3675 const size_t kBigValueSize = kControlFrameSizeLimit;
3676 string big_value(kBigValueSize, 'x');
3677 push_promise.SetHeader("aa", big_value);
3678 scoped_ptr<SpdyFrame> control_frame(
3679 framer.SerializePushPromise(push_promise));
3680 EXPECT_TRUE(control_frame.get() != NULL);
3681 EXPECT_GT(control_frame->size(),
3682 TestSpdyVisitor::sent_control_frame_max_size());
3684 TestSpdyVisitor visitor(spdy_version_);
3685 visitor.SimulateInFramer(
3686 reinterpret_cast<unsigned char*>(control_frame->data()),
3687 control_frame->size());
3688 EXPECT_TRUE(visitor.header_buffer_valid_);
3689 EXPECT_EQ(0, visitor.error_count_);
3690 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3691 EXPECT_EQ(16, visitor.continuation_count_);
3692 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3695 // Check that the framer stops delivering header data chunks once the visitor
3696 // declares it doesn't want any more. This is important to guard against
3697 // "zip bomb" types of attacks.
3698 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3699 const size_t kHeaderBufferChunks = 4;
3700 const size_t kHeaderBufferSize =
3701 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3702 const size_t kBigValueSize = kHeaderBufferSize * 2;
3703 string big_value(kBigValueSize, 'x');
3704 SpdyFramer framer(spdy_version_);
3705 SpdyHeadersIR headers(1);
3706 headers.set_priority(1);
3707 headers.set_fin(true);
3708 headers.SetHeader("aa", big_value);
3709 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3710 EXPECT_TRUE(control_frame.get() != NULL);
3711 TestSpdyVisitor visitor(spdy_version_);
3712 visitor.set_header_buffer_size(kHeaderBufferSize);
3713 visitor.use_compression_ = true;
3714 visitor.SimulateInFramer(
3715 reinterpret_cast<unsigned char*>(control_frame->data()),
3716 control_frame->size());
3717 EXPECT_FALSE(visitor.header_buffer_valid_);
3718 EXPECT_EQ(1, visitor.error_count_);
3719 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3720 visitor.framer_.error_code())
3721 << SpdyFramer::ErrorCodeToString(framer.error_code());
3723 // The framer should have stoped delivering chunks after the visitor
3724 // signaled "stop" by returning false from OnControlFrameHeaderData().
3726 // control_frame_header_data_count_ depends on the random sequence
3727 // produced by rand(), so adding, removing or running single tests
3728 // alters this value. The best we can do is assert that it happens
3729 // at least kHeaderBufferChunks + 1.
3730 EXPECT_LE(kHeaderBufferChunks + 1,
3731 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3732 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3734 // The framer should not have sent half-close to the visitor.
3735 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3738 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3739 if (spdy_version_ > SPDY3) {
3740 // Deflate compression doesn't apply to HPACK.
3741 return;
3743 SpdyFramer framer(spdy_version_);
3744 framer.set_enable_compression(false);
3745 // Construct a SYN_STREAM control frame without compressing the header block,
3746 // and have the framer try to decompress it. This will cause the framer to
3747 // deal with a decompression error.
3748 SpdySynStreamIR syn_stream(1);
3749 syn_stream.set_priority(1);
3750 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3751 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3752 TestSpdyVisitor visitor(spdy_version_);
3753 visitor.use_compression_ = true;
3754 visitor.SimulateInFramer(
3755 reinterpret_cast<unsigned char*>(control_frame->data()),
3756 control_frame->size());
3757 EXPECT_EQ(1, visitor.error_count_);
3758 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3759 << SpdyFramer::ErrorCodeToString(framer.error_code());
3760 EXPECT_EQ(0u, visitor.header_buffer_length_);
3763 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3764 SpdyFramer framer(spdy_version_);
3765 // Create a GoAway frame that has a few extra bytes at the end.
3766 // We create enough overhead to overflow the framer's control frame buffer.
3767 ASSERT_LE(SpdyFramer::kControlFrameBufferSize, 250u);
3768 const size_t length = SpdyFramer::kControlFrameBufferSize + 1;
3769 const unsigned char kV3FrameData[] = { // Also applies for V2.
3770 0x80, spdy_version_ch_, 0x00, 0x07,
3771 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
3772 0x00, 0x00, 0x00, 0x00, // Stream ID
3773 0x00, 0x00, 0x00, 0x00, // Status
3776 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3777 // since it may carry opaque data. Verify that minimal length is tested.
3778 ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
3779 const size_t less_than_min_length =
3780 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3781 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3782 const unsigned char kV4FrameData[] = {
3783 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
3784 0x00, 0x00, 0x00, 0x00,
3785 0x00, 0x00, 0x00, 0x00, // Stream Id
3786 0x00, 0x00, 0x00, 0x00, // Status
3787 0x00,
3789 const size_t pad_length =
3790 length + framer.GetControlFrameHeaderSize() -
3791 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3792 string pad(pad_length, 'A');
3793 TestSpdyVisitor visitor(spdy_version_);
3795 if (IsSpdy4()) {
3796 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3797 } else {
3798 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3800 visitor.SimulateInFramer(
3801 reinterpret_cast<const unsigned char*>(pad.c_str()),
3802 pad.length());
3804 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3805 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3806 visitor.framer_.error_code())
3807 << SpdyFramer::ErrorCodeToString(framer.error_code());
3808 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3811 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3812 SpdyFramer framer(spdy_version_);
3813 SpdySettingsIR settings_ir;
3814 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3815 SetFrameLength(control_frame.get(), 0, spdy_version_);
3816 TestSpdyVisitor visitor(spdy_version_);
3817 visitor.use_compression_ = false;
3818 visitor.SimulateInFramer(
3819 reinterpret_cast<unsigned char*>(control_frame->data()),
3820 framer.GetControlFrameHeaderSize());
3821 if (spdy_version_ <= SPDY3) {
3822 // Should generate an error, since zero-len settings frames are unsupported.
3823 EXPECT_EQ(1, visitor.error_count_);
3824 } else {
3825 // Zero-len settings frames are permitted as of SPDY 4.
3826 EXPECT_EQ(0, visitor.error_count_);
3830 // Tests handling of SETTINGS frames with invalid length.
3831 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3832 SpdyFramer framer(spdy_version_);
3833 SpdySettingsIR settings_ir;
3835 // Add a setting to pad the frame so that we don't get a buffer overflow when
3836 // calling SimulateInFramer() below.
3837 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3838 false,
3839 false,
3840 0x00000002);
3841 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3842 const size_t kNewLength = 14;
3843 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3844 TestSpdyVisitor visitor(spdy_version_);
3845 visitor.use_compression_ = false;
3846 visitor.SimulateInFramer(
3847 reinterpret_cast<unsigned char*>(control_frame->data()),
3848 framer.GetControlFrameHeaderSize() + kNewLength);
3849 // Should generate an error, since its not possible to have a
3850 // settings frame of length kNewLength.
3851 EXPECT_EQ(1, visitor.error_count_);
3854 // Tests handling of SETTINGS frames larger than the frame buffer size.
3855 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3856 SpdyFramer framer(spdy_version_);
3857 SpdySettingsIR settings_ir;
3858 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3859 false, // persist
3860 false, // persisted
3862 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3863 false, // persist
3864 false, // persisted
3866 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3867 false, // persist
3868 false, // persisted
3871 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3872 EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
3873 control_frame->size());
3874 TestSpdyVisitor visitor(spdy_version_);
3875 visitor.use_compression_ = false;
3877 // Read all at once.
3878 visitor.SimulateInFramer(
3879 reinterpret_cast<unsigned char*>(control_frame->data()),
3880 control_frame->size());
3881 EXPECT_EQ(0, visitor.error_count_);
3882 EXPECT_EQ(3, visitor.setting_count_);
3883 if (spdy_version_ > SPDY3) {
3884 EXPECT_EQ(1, visitor.settings_ack_sent_);
3887 // Read data in small chunks.
3888 size_t framed_data = 0;
3889 size_t unframed_data = control_frame->size();
3890 size_t kReadChunkSize = 5; // Read five bytes at a time.
3891 while (unframed_data > 0) {
3892 size_t to_read = std::min(kReadChunkSize, unframed_data);
3893 visitor.SimulateInFramer(
3894 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3895 to_read);
3896 unframed_data -= to_read;
3897 framed_data += to_read;
3899 EXPECT_EQ(0, visitor.error_count_);
3900 EXPECT_EQ(3 * 2, visitor.setting_count_);
3901 if (spdy_version_ > SPDY3) {
3902 EXPECT_EQ(2, visitor.settings_ack_sent_);
3906 // Tests handling of SETTINGS frame with duplicate entries.
3907 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3908 SpdyFramer framer(spdy_version_);
3910 const unsigned char kV2FrameData[] = {
3911 0x80, spdy_version_ch_, 0x00, 0x04,
3912 0x00, 0x00, 0x00, 0x1C,
3913 0x00, 0x00, 0x00, 0x03,
3914 0x01, 0x00, 0x00, 0x00, // 1st Setting
3915 0x00, 0x00, 0x00, 0x02,
3916 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3917 0x00, 0x00, 0x00, 0x03,
3918 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3919 0x00, 0x00, 0x00, 0x03,
3921 const unsigned char kV3FrameData[] = {
3922 0x80, spdy_version_ch_, 0x00, 0x04,
3923 0x00, 0x00, 0x00, 0x1C,
3924 0x00, 0x00, 0x00, 0x03,
3925 0x00, 0x00, 0x00, 0x01, // 1st Setting
3926 0x00, 0x00, 0x00, 0x02,
3927 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3928 0x00, 0x00, 0x00, 0x03,
3929 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3930 0x00, 0x00, 0x00, 0x03,
3932 const unsigned char kV4FrameData[] = {
3933 0x00, 0x00, 0x12, 0x04,
3934 0x00, 0x00, 0x00, 0x00,
3935 0x00, 0x00, 0x01, // 1st Setting
3936 0x00, 0x00, 0x00, 0x02,
3937 0x00, 0x01, // 2nd (duplicate) Setting
3938 0x00, 0x00, 0x00, 0x03,
3939 0x00, 0x03, // 3rd (unprocessed) Setting
3940 0x00, 0x00, 0x00, 0x03,
3943 TestSpdyVisitor visitor(spdy_version_);
3944 visitor.use_compression_ = false;
3945 if (IsSpdy2()) {
3946 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3947 } else if (IsSpdy3()) {
3948 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3949 } else {
3950 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3953 if (!IsSpdy4()) {
3954 EXPECT_EQ(1, visitor.setting_count_);
3955 EXPECT_EQ(1, visitor.error_count_);
3956 } else {
3957 // In SPDY 4+, duplicate settings are allowed;
3958 // each setting replaces the previous value for that setting.
3959 EXPECT_EQ(3, visitor.setting_count_);
3960 EXPECT_EQ(0, visitor.error_count_);
3961 EXPECT_EQ(1, visitor.settings_ack_sent_);
3965 // Tests handling of SETTINGS frame with a setting we don't recognize.
3966 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3967 SpdyFramer framer(spdy_version_);
3969 const unsigned char kV2FrameData[] = {
3970 0x80, spdy_version_ch_, 0x00, 0x04,
3971 0x00, 0x00, 0x00, 0x1C,
3972 0x00, 0x00, 0x00, 0x01,
3973 0x10, 0x00, 0x00, 0x00, // 1st Setting
3974 0x00, 0x00, 0x00, 0x02,
3976 const unsigned char kV3FrameData[] = {
3977 0x80, spdy_version_ch_, 0x00, 0x04,
3978 0x00, 0x00, 0x00, 0x1C,
3979 0x00, 0x00, 0x00, 0x01,
3980 0x00, 0x00, 0x00, 0x10, // 1st Setting
3981 0x00, 0x00, 0x00, 0x02,
3983 const unsigned char kV4FrameData[] = {
3984 0x00, 0x00, 0x06, 0x04,
3985 0x00, 0x00, 0x00, 0x00,
3986 0x00, 0x00, 0x10, // 1st Setting
3987 0x00, 0x00, 0x00, 0x02,
3990 TestSpdyVisitor visitor(spdy_version_);
3991 visitor.use_compression_ = false;
3992 if (IsSpdy2()) {
3993 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3994 } else if (IsSpdy3()) {
3995 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3996 } else {
3997 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4000 if (!IsSpdy4()) {
4001 EXPECT_EQ(0, visitor.setting_count_);
4002 EXPECT_EQ(1, visitor.error_count_);
4003 } else {
4004 // In SPDY 4+, we ignore unknown settings because of extensions.
4005 EXPECT_EQ(0, visitor.setting_count_);
4006 EXPECT_EQ(0, visitor.error_count_);
4010 // Tests handling of SETTINGS frame with entries out of order.
4011 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
4012 SpdyFramer framer(spdy_version_);
4014 const unsigned char kV2FrameData[] = {
4015 0x80, spdy_version_ch_, 0x00, 0x04,
4016 0x00, 0x00, 0x00, 0x1C,
4017 0x00, 0x00, 0x00, 0x03,
4018 0x02, 0x00, 0x00, 0x00, // 1st Setting
4019 0x00, 0x00, 0x00, 0x02,
4020 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4021 0x00, 0x00, 0x00, 0x03,
4022 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4023 0x00, 0x00, 0x00, 0x03,
4025 const unsigned char kV3FrameData[] = {
4026 0x80, spdy_version_ch_, 0x00, 0x04,
4027 0x00, 0x00, 0x00, 0x1C,
4028 0x00, 0x00, 0x00, 0x03,
4029 0x00, 0x00, 0x00, 0x02, // 1st Setting
4030 0x00, 0x00, 0x00, 0x02,
4031 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4032 0x00, 0x00, 0x00, 0x03,
4033 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4034 0x00, 0x00, 0x00, 0x03,
4036 const unsigned char kV4FrameData[] = {
4037 0x00, 0x00, 0x12, 0x04,
4038 0x00, 0x00, 0x00, 0x00,
4039 0x00, 0x00, 0x02, // 1st Setting
4040 0x00, 0x00, 0x00, 0x02,
4041 0x00, 0x01, // 2nd (out of order) Setting
4042 0x00, 0x00, 0x00, 0x03,
4043 0x00, 0x03, // 3rd (unprocessed) Setting
4044 0x00, 0x00, 0x00, 0x03,
4047 TestSpdyVisitor visitor(spdy_version_);
4048 visitor.use_compression_ = false;
4049 if (IsSpdy2()) {
4050 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4051 } else if (IsSpdy3()) {
4052 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4053 } else {
4054 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4057 if (!IsSpdy4()) {
4058 EXPECT_EQ(1, visitor.setting_count_);
4059 EXPECT_EQ(1, visitor.error_count_);
4060 } else {
4061 // In SPDY 4+, settings are allowed in any order.
4062 EXPECT_EQ(3, visitor.setting_count_);
4063 EXPECT_EQ(0, visitor.error_count_);
4067 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4068 if (spdy_version_ <= SPDY3) {
4069 return;
4071 SpdyFramer framer(spdy_version_);
4073 const unsigned char kFrameData[] = {
4074 0x00, 0x00, 0x00, 0x04, 0x01,
4075 0x00, 0x00, 0x00, 0x00,
4078 TestSpdyVisitor visitor(spdy_version_);
4079 visitor.use_compression_ = false;
4080 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4082 EXPECT_EQ(0, visitor.error_count_);
4083 EXPECT_EQ(0, visitor.setting_count_);
4084 EXPECT_EQ(1, visitor.settings_ack_received_);
4087 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4088 if (spdy_version_ <= SPDY3) {
4089 return;
4092 const int kPaddingLen = 119;
4093 const char data_payload[] = "hello";
4095 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4096 SpdyFramer framer(spdy_version_);
4097 framer.set_visitor(&visitor);
4099 SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
4100 data_ir.set_padding_len(kPaddingLen);
4101 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4102 ASSERT_TRUE(frame.get() != NULL);
4104 int bytes_consumed = 0;
4106 // Send the frame header.
4107 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4108 kPaddingLen + strlen(data_payload),
4109 false));
4110 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4111 framer.ProcessInput(frame->data(),
4112 framer.GetDataFrameMinimumSize()));
4113 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4114 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4115 bytes_consumed += framer.GetDataFrameMinimumSize();
4117 // Send the padding length field.
4118 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4119 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4120 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4121 bytes_consumed += 1;
4123 // Send the first two bytes of the data payload, i.e., "he".
4124 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4125 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4126 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4127 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4128 bytes_consumed += 2;
4130 // Send the rest three bytes of the data payload, i.e., "llo".
4131 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4132 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4133 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4134 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4135 bytes_consumed += 3;
4137 // Send the first 100 bytes of the padding payload.
4138 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false));
4139 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4140 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4141 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4142 bytes_consumed += 100;
4144 // Send rest of the padding payload.
4145 EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 18, false));
4146 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4147 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
4148 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4151 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4152 SpdyFramer framer(spdy_version_);
4153 scoped_ptr<SpdyFrame> control_frame(
4154 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4155 TestSpdyVisitor visitor(spdy_version_);
4156 visitor.SimulateInFramer(
4157 reinterpret_cast<unsigned char*>(control_frame->data()),
4158 control_frame->size());
4159 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4160 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4163 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4164 if (!IsSpdy3()) {
4165 return;
4167 SpdyFramer framer(spdy_version_);
4168 const unsigned char kV3FrameData[] = { // Also applies for V2.
4169 0x80, spdy_version_ch_, 0x00, 0x0A,
4170 0x00, 0x00, 0x00, 0x33,
4171 0x00, 0x03, 0x00, 0x00,
4172 0x00, 0x05, 'p', 'r',
4173 'o', 'o', 'f', 0x00,
4174 0x00, 0x00, 0x06, 'a',
4175 ' ', 'c', 'e', 'r',
4176 't', 0x00, 0x00, 0x00,
4177 0x0C, 'a', 'n', 'o',
4178 't', 'h', 'e', 'r',
4179 ' ', 'c', 'e', 'r',
4180 't', 0x00, 0x00, 0x00,
4181 0x0A, 'f', 'i', 'n',
4182 'a', 'l', ' ', 'c',
4183 'e', 'r', 't',
4185 TestSpdyVisitor visitor(spdy_version_);
4186 visitor.use_compression_ = false;
4187 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4188 EXPECT_EQ(0, visitor.error_count_);
4191 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4192 if (!IsSpdy3()) {
4193 return;
4195 SpdyFramer framer(spdy_version_);
4196 const unsigned char kV3FrameData[] = { // Also applies for V2.
4197 0x80, spdy_version_ch_, 0x00, 0x0A,
4198 0x00, 0x00, 0x00, 0x33,
4199 0x00, 0x03, 0x00, 0x00,
4200 0x00, 0x05, 'p', 'r',
4201 'o', 'o', 'f', 0x00,
4202 0x00, 0x00, 0x06, 'a',
4203 ' ', 'c', 'e', 'r',
4204 't', 0x00, 0x00, 0x00,
4205 0x0C, 'a', 'n', 'o',
4206 't', 'h', 'e', 'r',
4207 ' ', 'c', 'e', 'r',
4208 't', 0x00, 0x00, 0x00,
4209 0x0A, 'f', 'i', 'n',
4210 'a', 'l', ' ', 'c',
4211 'e', 'r', 't',
4213 TestSpdyVisitor visitor(spdy_version_);
4214 visitor.use_compression_ = false;
4215 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4216 arraysize(kV3FrameData));
4217 scoped_ptr<SpdyFrame> control_frame(
4218 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4219 multiple_frame_data.append(string(control_frame->data(),
4220 control_frame->size()));
4221 visitor.SimulateInFramer(
4222 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4223 multiple_frame_data.length());
4224 EXPECT_EQ(0, visitor.error_count_);
4225 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4226 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4229 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4230 if (spdy_version_ <= SPDY3) {
4231 return;
4234 SpdyFramer framer(spdy_version_);
4235 SpdyPushPromiseIR push_promise(42, 57);
4236 push_promise.SetHeader("foo", "bar");
4237 push_promise.SetHeader("bar", "foofoo");
4238 SpdyHeaderBlock headers = push_promise.name_value_block();
4239 scoped_ptr<SpdySerializedFrame> frame(
4240 framer.SerializePushPromise(push_promise));
4241 EXPECT_TRUE(frame.get() != NULL);
4242 TestSpdyVisitor visitor(spdy_version_);
4243 visitor.use_compression_ = true;
4244 visitor.SimulateInFramer(
4245 reinterpret_cast<unsigned char*>(frame->data()),
4246 frame->size());
4247 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4248 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4249 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4252 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4253 if (spdy_version_ <= SPDY3) {
4254 return;
4257 const unsigned char kInput[] = {
4258 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4259 0x00, 0x00, 0x00, 0x01, // Stream 1
4260 0x03, // Padding of 3.
4261 0x00, 0x06, 0x63, 0x6f,
4262 0x6f, 0x6b, 0x69, 0x65,
4263 0x07, 0x66, 0x6f, 0x6f,
4264 0x3d, 0x62, 0x61, 0x72,
4265 0x00, 0x00, 0x00,
4267 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4268 0x00, 0x00, 0x00, 0x01, // Stream 1
4269 0x00, 0x06, 0x63, 0x6f,
4270 0x6f, 0x6b, 0x69, 0x65,
4271 0x08, 0x62, 0x61, 0x7a,
4272 0x3d, 0x62, 0x69, 0x6e,
4273 0x67, 0x00, 0x06, 0x63,
4275 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4276 0x00, 0x00, 0x00, 0x01, // Stream 1
4277 0x6f, 0x6f, 0x6b, 0x69,
4278 0x65, 0x00, 0x00, 0x04,
4279 0x6e, 0x61, 0x6d, 0x65,
4280 0x05, 0x76, 0x61, 0x6c,
4281 0x75, 0x65,
4284 TestSpdyVisitor visitor(spdy_version_);
4285 visitor.SimulateInFramer(kInput, sizeof(kInput));
4287 EXPECT_EQ(0, visitor.error_count_);
4288 EXPECT_EQ(1, visitor.headers_frame_count_);
4289 EXPECT_EQ(2, visitor.continuation_count_);
4290 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4291 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4293 EXPECT_THAT(visitor.headers_,
4294 testing::ElementsAre(
4295 testing::Pair("cookie", "foo=bar; baz=bing; "),
4296 testing::Pair("name", "value")));
4299 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4300 if (spdy_version_ <= SPDY3) {
4301 return;
4304 const unsigned char kInput[] = {
4305 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4306 0x00, 0x00, 0x00, 0x01, // Stream 1
4307 0x00, 0x06, 0x63, 0x6f,
4308 0x6f, 0x6b, 0x69, 0x65,
4309 0x07, 0x66, 0x6f, 0x6f,
4310 0x3d, 0x62, 0x61, 0x72,
4312 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4313 0x00, 0x00, 0x00, 0x01, // Stream 1
4314 0x00, 0x06, 0x63, 0x6f,
4315 0x6f, 0x6b, 0x69, 0x65,
4316 0x08, 0x62, 0x61, 0x7a,
4317 0x3d, 0x62, 0x69, 0x6e,
4318 0x67, 0x00, 0x06, 0x63,
4320 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4321 0x00, 0x00, 0x00, 0x01, // Stream 1
4322 0x6f, 0x6f, 0x6b, 0x69,
4323 0x65, 0x00, 0x00, 0x04,
4324 0x6e, 0x61, 0x6d, 0x65,
4325 0x05, 0x76, 0x61, 0x6c,
4326 0x75, 0x65,
4329 SpdyFramer framer(spdy_version_);
4330 TestSpdyVisitor visitor(spdy_version_);
4331 visitor.SimulateInFramer(kInput, sizeof(kInput));
4333 EXPECT_EQ(0, visitor.error_count_);
4334 EXPECT_EQ(1, visitor.headers_frame_count_);
4335 EXPECT_EQ(2, visitor.continuation_count_);
4336 EXPECT_EQ(1, visitor.fin_flag_count_);
4337 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4338 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4340 EXPECT_THAT(visitor.headers_,
4341 testing::ElementsAre(
4342 testing::Pair("cookie", "foo=bar; baz=bing; "),
4343 testing::Pair("name", "value")));
4346 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4347 if (spdy_version_ <= SPDY3) {
4348 return;
4351 const unsigned char kInput[] = {
4352 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4353 0x08, 0x00, 0x00, 0x00, // PADDED
4354 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4355 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4356 0x63, 0x6f, 0x6f, 0x6b,
4357 0x69, 0x65, 0x07, 0x66,
4358 0x6f, 0x6f, 0x3d, 0x62,
4359 0x61, 0x72, 0x00, 0x00,
4361 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4362 0x00, 0x00, 0x00, 0x00,
4363 0x01, 0x00, 0x06, 0x63, // Stream 1
4364 0x6f, 0x6f, 0x6b, 0x69,
4365 0x65, 0x08, 0x62, 0x61,
4366 0x7a, 0x3d, 0x62, 0x69,
4367 0x6e, 0x67, 0x00, 0x06,
4368 0x63,
4370 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4371 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4372 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4373 0x69, 0x65, 0x00, 0x00,
4374 0x04, 0x6e, 0x61, 0x6d,
4375 0x65, 0x05, 0x76, 0x61,
4376 0x6c, 0x75, 0x65,
4379 SpdyFramer framer(spdy_version_);
4380 TestSpdyVisitor visitor(spdy_version_);
4381 visitor.SimulateInFramer(kInput, sizeof(kInput));
4383 EXPECT_EQ(0, visitor.error_count_);
4384 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4385 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4386 EXPECT_EQ(2, visitor.continuation_count_);
4387 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4388 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4390 EXPECT_THAT(visitor.headers_,
4391 testing::ElementsAre(
4392 testing::Pair("cookie", "foo=bar; baz=bing; "),
4393 testing::Pair("name", "value")));
4396 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4397 if (spdy_version_ <= SPDY3) {
4398 return;
4401 const unsigned char kInput[] = {
4402 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4403 0x00, 0x00, 0x00, 0x01, // Stream 1
4404 0x00, 0x06, 0x63, 0x6f,
4405 0x6f, 0x6b, 0x69, 0x65,
4406 0x07, 0x66, 0x6f, 0x6f,
4407 0x3d, 0x62, 0x61, 0x72,
4409 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4410 0x00, 0x00, 0x00, 0x02, // Stream 2
4411 0x00, 0x06, 0x63, 0x6f,
4412 0x6f, 0x6b, 0x69, 0x65,
4413 0x08, 0x62, 0x61, 0x7a,
4414 0x3d, 0x62, 0x69, 0x6e,
4415 0x67, 0x00, 0x06, 0x63,
4418 SpdyFramer framer(spdy_version_);
4419 TestSpdyVisitor visitor(spdy_version_);
4420 framer.set_visitor(&visitor);
4421 visitor.SimulateInFramer(kInput, sizeof(kInput));
4423 EXPECT_EQ(1, visitor.error_count_);
4424 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4425 visitor.framer_.error_code())
4426 << SpdyFramer::ErrorCodeToString(framer.error_code());
4427 EXPECT_EQ(1, visitor.headers_frame_count_);
4428 EXPECT_EQ(0, visitor.continuation_count_);
4429 EXPECT_EQ(0u, visitor.header_buffer_length_);
4432 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4433 if (spdy_version_ <= SPDY3) {
4434 return;
4437 const unsigned char kInput[] = {
4438 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4439 0x00, 0x00, 0x00, 0x01, // Stream 1
4440 0x00, 0x06, 0x63, 0x6f,
4441 0x6f, 0x6b, 0x69, 0x65,
4442 0x07, 0x66, 0x6f, 0x6f,
4443 0x3d, 0x62, 0x61, 0x72,
4446 SpdyFramer framer(spdy_version_);
4447 TestSpdyVisitor visitor(spdy_version_);
4448 framer.set_visitor(&visitor);
4449 visitor.SimulateInFramer(kInput, sizeof(kInput));
4451 EXPECT_EQ(1, visitor.error_count_);
4452 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4453 visitor.framer_.error_code())
4454 << SpdyFramer::ErrorCodeToString(framer.error_code());
4455 EXPECT_EQ(0, visitor.continuation_count_);
4456 EXPECT_EQ(0u, visitor.header_buffer_length_);
4459 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4460 if (spdy_version_ <= SPDY3) {
4461 return;
4464 const unsigned char kInput[] = {
4465 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4466 0x00, 0x00, 0x00, 0x01, // Stream 1
4467 0x00, 0x06, 0x63, 0x6f,
4468 0x6f, 0x6b, 0x69, 0x65,
4469 0x07, 0x66, 0x6f, 0x6f,
4470 0x3d, 0x62, 0x61, 0x72,
4472 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4473 0x00, 0x00, 0x00, 0x04,
4474 0xde, 0xad, 0xbe, 0xef,
4477 SpdyFramer framer(spdy_version_);
4478 TestSpdyVisitor visitor(spdy_version_);
4479 framer.set_visitor(&visitor);
4480 visitor.SimulateInFramer(kInput, sizeof(kInput));
4482 EXPECT_EQ(1, visitor.error_count_);
4483 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4484 visitor.framer_.error_code())
4485 << SpdyFramer::ErrorCodeToString(framer.error_code());
4486 EXPECT_EQ(1, visitor.headers_frame_count_);
4487 EXPECT_EQ(0, visitor.continuation_count_);
4488 EXPECT_EQ(0u, visitor.header_buffer_length_);
4489 EXPECT_EQ(0, visitor.data_frame_count_);
4492 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4493 if (spdy_version_ <= SPDY3) {
4494 return;
4497 const unsigned char kInput[] = {
4498 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4499 0x00, 0x00, 0x00, 0x01, // Stream 1
4500 0x00, 0x06, 0x63, 0x6f,
4501 0x6f, 0x6b, 0x69, 0x65,
4502 0x07, 0x66, 0x6f, 0x6f,
4503 0x3d, 0x62, 0x61, 0x72,
4505 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4506 0x00, 0x00, 0x00, 0x01, // Stream 1
4507 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4508 0x6f, 0x6b, 0x69, 0x65,
4509 0x08, 0x62, 0x61, 0x7a,
4510 0x3d, 0x62, 0x69, 0x6e,
4511 0x67, 0x00, 0x06, 0x63,
4514 SpdyFramer framer(spdy_version_);
4515 TestSpdyVisitor visitor(spdy_version_);
4516 framer.set_visitor(&visitor);
4517 visitor.SimulateInFramer(kInput, sizeof(kInput));
4519 EXPECT_EQ(1, visitor.error_count_);
4520 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4521 visitor.framer_.error_code())
4522 << SpdyFramer::ErrorCodeToString(framer.error_code());
4523 EXPECT_EQ(1, visitor.headers_frame_count_);
4524 EXPECT_EQ(0, visitor.continuation_count_);
4525 EXPECT_EQ(0u, visitor.header_buffer_length_);
4526 EXPECT_EQ(0, visitor.data_frame_count_);
4529 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4530 if (spdy_version_ <= SPDY3) {
4531 return;
4533 const unsigned char kInput[] = {
4534 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4535 0x00, 0x00, 0x00, 0x01, // Stream 1
4536 0xde, 0xad, 0xbe, 0xef,
4537 0xde, 0xad, 0xbe, 0xef,
4538 0xde, 0xad, 0xbe, 0xef,
4541 TestSpdyVisitor visitor(spdy_version_);
4542 visitor.SimulateInFramer(kInput, sizeof(kInput));
4544 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4545 EXPECT_EQ(0, visitor.error_count_);
4546 EXPECT_EQ(12, visitor.data_bytes_);
4547 EXPECT_EQ(0, visitor.fin_frame_count_);
4548 EXPECT_EQ(0, visitor.fin_flag_count_);
4551 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4552 if (spdy_version_ <= SPDY3) {
4553 return;
4555 const unsigned char kInput[] = {
4556 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4557 0x00, 0x00, 0x00, 0x01, // Stream 1
4558 0x00, 0x06, 0x63, 0x6f,
4559 0x6f, 0x6b, 0x69, 0x65,
4560 0x07, 0x66, 0x6f, 0x6f,
4561 0x3d, 0x62, 0x61, 0x72,
4564 TestSpdyVisitor visitor(spdy_version_);
4565 visitor.SimulateInFramer(kInput, sizeof(kInput));
4567 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4568 EXPECT_EQ(0, visitor.error_count_);
4569 EXPECT_EQ(1, visitor.headers_frame_count_);
4570 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4572 EXPECT_THAT(visitor.headers_,
4573 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4576 TEST_P(SpdyFramerTest, ReadGarbage) {
4577 SpdyFramer framer(spdy_version_);
4578 unsigned char garbage_frame[256];
4579 memset(garbage_frame, ~0, sizeof(garbage_frame));
4580 TestSpdyVisitor visitor(spdy_version_);
4581 visitor.use_compression_ = false;
4582 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4583 EXPECT_EQ(1, visitor.error_count_);
4586 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4587 if (spdy_version_ <= SPDY3) {
4588 return;
4590 SpdyFramer framer(spdy_version_);
4592 // The unrecognized frame type should still have a valid length.
4593 const unsigned char unknown_frame[] = {
4594 0x00, 0x00, 0x08, 0xff, 0xff,
4595 0xff, 0xff, 0xff, 0xff,
4596 0xff, 0xff, 0xff, 0xff,
4597 0xff, 0xff, 0xff, 0xff,
4599 TestSpdyVisitor visitor(spdy_version_);
4601 // Simulate the case where the stream id validation checks out.
4602 visitor.on_unknown_frame_result_ = true;
4603 visitor.use_compression_ = false;
4604 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4605 EXPECT_EQ(0, visitor.error_count_);
4607 // Follow it up with a valid control frame to make sure we handle
4608 // subsequent frames correctly.
4609 SpdySettingsIR settings_ir;
4610 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4611 false, // persist
4612 false, // persisted
4613 10);
4614 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4615 visitor.SimulateInFramer(
4616 reinterpret_cast<unsigned char*>(control_frame->data()),
4617 control_frame->size());
4618 EXPECT_EQ(0, visitor.error_count_);
4619 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4620 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4623 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4624 if (!IsSpdy4()) {
4625 return;
4627 SpdyFramer framer(spdy_version_);
4628 const unsigned char kFrameData[] = {
4629 0x00, 0x00, 0x08, 0xff, 0xff,
4630 0xff, 0xff, 0xff, 0xff,
4631 0xff, 0xff, 0xff, 0xff,
4632 0xff, 0xff, 0xff, 0xff,
4634 TestSpdyVisitor visitor(spdy_version_);
4635 visitor.use_compression_ = false;
4636 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4637 EXPECT_EQ(1, visitor.error_count_);
4640 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4641 if (IsSpdy4()) {
4642 // Not valid for SPDY 4 since there is no version field.
4643 return;
4645 SpdyFramer framer(spdy_version_);
4646 const unsigned char kFrameData[] = {
4647 0x80, spdy_version_ch_, 0xff, 0xff,
4648 0xff, 0xff, 0xff, 0xff,
4650 TestSpdyVisitor visitor(spdy_version_);
4651 visitor.use_compression_ = false;
4652 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4653 EXPECT_EQ(1, visitor.error_count_);
4656 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4657 if (spdy_version_ <= SPDY3) {
4658 return;
4660 const unsigned char kInput[] = {
4661 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4662 0x00, 0x00, 0x00, 0x01, // Stream 1
4663 0xef, 0xef, 0xff, 0xff,
4664 0xff, 0xff, 0xff, 0xff,
4665 0xff, 0xff, 0xff, 0xff,
4666 0xff, 0xff, 0xff, 0xff,
4667 0xff, 0xff,
4670 TestSpdyVisitor visitor(spdy_version_);
4671 visitor.SimulateInFramer(kInput, arraysize(kInput));
4672 EXPECT_EQ(1, visitor.error_count_);
4675 TEST_P(SpdyFramerTest, SizesTest) {
4676 SpdyFramer framer(spdy_version_);
4677 if (IsSpdy4() || IsSpdy5()) {
4678 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4679 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4680 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4681 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4682 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4683 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4684 EXPECT_EQ(17u, framer.GetPingSize());
4685 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4686 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4687 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4688 EXPECT_EQ(9u, framer.GetBlockedSize());
4689 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4690 EXPECT_EQ(18u, framer.GetAltSvcMinimumSize());
4691 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4692 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4693 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4694 } else {
4695 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4696 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4697 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4698 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4699 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4700 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4701 EXPECT_EQ(12u, framer.GetPingSize());
4702 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4703 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4704 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4705 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4706 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4707 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4711 TEST_P(SpdyFramerTest, StateToStringTest) {
4712 EXPECT_STREQ("ERROR",
4713 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4714 EXPECT_STREQ("AUTO_RESET",
4715 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4716 EXPECT_STREQ("RESET",
4717 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4718 EXPECT_STREQ("READING_COMMON_HEADER",
4719 SpdyFramer::StateToString(
4720 SpdyFramer::SPDY_READING_COMMON_HEADER));
4721 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4722 SpdyFramer::StateToString(
4723 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4724 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4725 SpdyFramer::StateToString(
4726 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4727 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4728 SpdyFramer::StateToString(
4729 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4730 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4731 SpdyFramer::StateToString(
4732 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4733 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4734 SpdyFramer::StateToString(
4735 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4736 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4737 SpdyFramer::StateToString(
4738 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4739 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4740 SpdyFramer::StateToString(
4741 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4742 EXPECT_STREQ("UNKNOWN_STATE",
4743 SpdyFramer::StateToString(
4744 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4747 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4748 EXPECT_STREQ("NO_ERROR",
4749 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4750 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4751 SpdyFramer::ErrorCodeToString(
4752 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4753 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4754 SpdyFramer::ErrorCodeToString(
4755 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4756 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4757 SpdyFramer::ErrorCodeToString(
4758 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4759 EXPECT_STREQ("UNSUPPORTED_VERSION",
4760 SpdyFramer::ErrorCodeToString(
4761 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4762 EXPECT_STREQ("DECOMPRESS_FAILURE",
4763 SpdyFramer::ErrorCodeToString(
4764 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4765 EXPECT_STREQ("COMPRESS_FAILURE",
4766 SpdyFramer::ErrorCodeToString(
4767 SpdyFramer::SPDY_COMPRESS_FAILURE));
4768 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4769 SpdyFramer::ErrorCodeToString(
4770 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4771 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4772 SpdyFramer::ErrorCodeToString(
4773 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4774 EXPECT_STREQ("UNKNOWN_ERROR",
4775 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4778 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4779 EXPECT_STREQ("INVALID",
4780 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4781 EXPECT_STREQ("PROTOCOL_ERROR",
4782 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4783 EXPECT_STREQ("INVALID_STREAM",
4784 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4785 EXPECT_STREQ("REFUSED_STREAM",
4786 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4787 EXPECT_STREQ("UNSUPPORTED_VERSION",
4788 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4789 EXPECT_STREQ("CANCEL",
4790 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4791 EXPECT_STREQ("INTERNAL_ERROR",
4792 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4793 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4794 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4795 EXPECT_STREQ("UNKNOWN_STATUS",
4796 SpdyFramer::StatusCodeToString(-1));
4799 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4800 EXPECT_STREQ("DATA",
4801 SpdyFramer::FrameTypeToString(DATA));
4802 EXPECT_STREQ("SYN_STREAM",
4803 SpdyFramer::FrameTypeToString(SYN_STREAM));
4804 EXPECT_STREQ("SYN_REPLY",
4805 SpdyFramer::FrameTypeToString(SYN_REPLY));
4806 EXPECT_STREQ("RST_STREAM",
4807 SpdyFramer::FrameTypeToString(RST_STREAM));
4808 EXPECT_STREQ("SETTINGS",
4809 SpdyFramer::FrameTypeToString(SETTINGS));
4810 EXPECT_STREQ("PING",
4811 SpdyFramer::FrameTypeToString(PING));
4812 EXPECT_STREQ("GOAWAY",
4813 SpdyFramer::FrameTypeToString(GOAWAY));
4814 EXPECT_STREQ("HEADERS",
4815 SpdyFramer::FrameTypeToString(HEADERS));
4816 EXPECT_STREQ("WINDOW_UPDATE",
4817 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4818 EXPECT_STREQ("PUSH_PROMISE",
4819 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4820 EXPECT_STREQ("CREDENTIAL",
4821 SpdyFramer::FrameTypeToString(CREDENTIAL));
4822 EXPECT_STREQ("CONTINUATION",
4823 SpdyFramer::FrameTypeToString(CONTINUATION));
4826 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4827 if (IsSpdy4()) {
4828 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4829 return;
4832 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4833 SpdyFramer framer(spdy_version_);
4834 framer.set_visitor(&visitor);
4836 EXPECT_CALL(visitor, OnError(_));
4837 framer.ProcessInput("HTTP/1.1", 8);
4838 EXPECT_TRUE(framer.probable_http_response());
4839 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4840 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4841 << SpdyFramer::ErrorCodeToString(framer.error_code());
4844 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4845 SpdyFramer framer(spdy_version_);
4846 framer.set_visitor(&visitor);
4848 EXPECT_CALL(visitor, OnError(_));
4849 framer.ProcessInput("HTTP/1.0", 8);
4850 EXPECT_TRUE(framer.probable_http_response());
4851 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4852 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4853 << SpdyFramer::ErrorCodeToString(framer.error_code());
4857 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4858 if (spdy_version_ > SPDY3) {
4859 return;
4862 uint8 flags = 0;
4863 do {
4864 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4866 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4867 SpdyFramer framer(spdy_version_);
4868 framer.set_visitor(&visitor);
4870 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4871 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4872 SetFrameFlags(frame.get(), flags, spdy_version_);
4874 if (flags & ~DATA_FLAG_FIN) {
4875 EXPECT_CALL(visitor, OnError(_));
4876 } else {
4877 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4878 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4879 if (flags & DATA_FLAG_FIN) {
4880 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4884 framer.ProcessInput(frame->data(), frame->size());
4885 if (flags & ~DATA_FLAG_FIN) {
4886 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4887 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4888 framer.error_code())
4889 << SpdyFramer::ErrorCodeToString(framer.error_code());
4890 } else {
4891 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4892 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4893 << SpdyFramer::ErrorCodeToString(framer.error_code());
4895 } while (++flags != 0);
4898 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4899 if (spdy_version_ <= SPDY3) {
4900 return;
4903 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4904 DATA_FLAG_PADDED;
4906 uint8 flags = 0;
4907 do {
4908 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4910 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4911 SpdyFramer framer(spdy_version_);
4912 framer.set_visitor(&visitor);
4914 SpdyDataIR data_ir(1, StringPiece("hello", 5));
4915 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4916 SetFrameFlags(frame.get(), flags, spdy_version_);
4918 if (flags & ~valid_data_flags) {
4919 EXPECT_CALL(visitor, OnError(_));
4920 } else {
4921 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4922 if (flags & DATA_FLAG_PADDED) {
4923 // Expect Error since we don't set padded in payload.
4924 EXPECT_CALL(visitor, OnError(_));
4925 } else {
4926 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4927 if (flags & DATA_FLAG_FIN) {
4928 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4933 framer.ProcessInput(frame->data(), frame->size());
4934 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
4935 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4936 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4937 framer.error_code())
4938 << SpdyFramer::ErrorCodeToString(framer.error_code());
4939 } else {
4940 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4941 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4942 << SpdyFramer::ErrorCodeToString(framer.error_code());
4944 } while (++flags != 0);
4947 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4948 if (!IsSpdy2() && !IsSpdy3()) {
4949 // SYN_STREAM not supported in SPDY>3
4950 return;
4952 uint8 flags = 0;
4953 do {
4954 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4956 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4957 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4958 SpdyFramer framer(spdy_version_);
4959 framer.set_visitor(&visitor);
4960 framer.set_debug_visitor(&debug_visitor);
4962 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4964 SpdySynStreamIR syn_stream(8);
4965 syn_stream.set_associated_to_stream_id(3);
4966 syn_stream.set_priority(1);
4967 syn_stream.SetHeader("foo", "bar");
4968 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4969 SetFrameFlags(frame.get(), flags, spdy_version_);
4971 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4972 EXPECT_CALL(visitor, OnError(_));
4973 } else {
4974 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
4975 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
4976 flags & CONTROL_FLAG_UNIDIRECTIONAL));
4977 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
4978 .WillRepeatedly(testing::Return(true));
4979 if (flags & DATA_FLAG_FIN) {
4980 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4981 } else {
4982 // Do not close the stream if we are expecting a CONTINUATION frame.
4983 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
4987 framer.ProcessInput(frame->data(), frame->size());
4988 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4989 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4990 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
4991 framer.error_code())
4992 << SpdyFramer::ErrorCodeToString(framer.error_code());
4993 } else {
4994 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4995 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4996 << SpdyFramer::ErrorCodeToString(framer.error_code());
4998 } while (++flags != 0);
5001 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
5002 if (!IsSpdy2() && !IsSpdy3()) {
5003 // SYN_REPLY not supported in SPDY>3
5004 return;
5006 uint8 flags = 0;
5007 do {
5008 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5010 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5011 SpdyFramer framer(spdy_version_);
5012 framer.set_visitor(&visitor);
5014 SpdySynReplyIR syn_reply(37);
5015 syn_reply.SetHeader("foo", "bar");
5016 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5017 SetFrameFlags(frame.get(), flags, spdy_version_);
5019 if (flags & ~CONTROL_FLAG_FIN) {
5020 EXPECT_CALL(visitor, OnError(_));
5021 } else {
5022 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5023 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5024 .WillRepeatedly(testing::Return(true));
5025 if (flags & DATA_FLAG_FIN) {
5026 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5030 framer.ProcessInput(frame->data(), frame->size());
5031 if (flags & ~CONTROL_FLAG_FIN) {
5032 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5033 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5034 framer.error_code())
5035 << SpdyFramer::ErrorCodeToString(framer.error_code());
5036 } else {
5037 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5038 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5039 << SpdyFramer::ErrorCodeToString(framer.error_code());
5041 } while (++flags != 0);
5044 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5045 uint8 flags = 0;
5046 do {
5047 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5049 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5050 SpdyFramer framer(spdy_version_);
5051 framer.set_visitor(&visitor);
5053 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5054 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5055 SetFrameFlags(frame.get(), flags, spdy_version_);
5057 if (flags != 0) {
5058 EXPECT_CALL(visitor, OnError(_));
5059 } else {
5060 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5063 framer.ProcessInput(frame->data(), frame->size());
5064 if (flags != 0) {
5065 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5066 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5067 framer.error_code())
5068 << SpdyFramer::ErrorCodeToString(framer.error_code());
5069 } else {
5070 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5071 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5072 << SpdyFramer::ErrorCodeToString(framer.error_code());
5074 } while (++flags != 0);
5077 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5078 if (spdy_version_ > SPDY3) { return; }
5079 uint8 flags = 0;
5080 do {
5081 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5083 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5084 SpdyFramer framer(spdy_version_);
5085 framer.set_visitor(&visitor);
5087 SpdySettingsIR settings_ir;
5088 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5089 false,
5090 false,
5091 54321);
5092 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5093 SetFrameFlags(frame.get(), flags, spdy_version_);
5095 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5096 EXPECT_CALL(visitor, OnError(_));
5097 } else {
5098 EXPECT_CALL(visitor, OnSettings(
5099 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5100 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5101 SETTINGS_FLAG_NONE, 54321));
5102 EXPECT_CALL(visitor, OnSettingsEnd());
5105 framer.ProcessInput(frame->data(), frame->size());
5106 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5107 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5108 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5109 framer.error_code())
5110 << SpdyFramer::ErrorCodeToString(framer.error_code());
5111 } else {
5112 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5113 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5114 << SpdyFramer::ErrorCodeToString(framer.error_code());
5116 } while (++flags != 0);
5119 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5120 if (spdy_version_ <= SPDY3) { return; }
5121 uint8 flags = 0;
5122 do {
5123 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5125 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5126 SpdyFramer framer(spdy_version_);
5127 framer.set_visitor(&visitor);
5129 SpdySettingsIR settings_ir;
5130 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5131 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5132 SetFrameFlags(frame.get(), flags, spdy_version_);
5134 if (flags != 0) {
5135 EXPECT_CALL(visitor, OnError(_));
5136 } else {
5137 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5138 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5139 EXPECT_CALL(visitor, OnSettingsEnd());
5142 framer.ProcessInput(frame->data(), frame->size());
5143 if (flags & ~SETTINGS_FLAG_ACK) {
5144 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5145 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5146 framer.error_code())
5147 << SpdyFramer::ErrorCodeToString(framer.error_code());
5148 } else if (flags & SETTINGS_FLAG_ACK) {
5149 // The frame is invalid because ACK frames should have no payload.
5150 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5151 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5152 framer.error_code())
5153 << SpdyFramer::ErrorCodeToString(framer.error_code());
5154 } else {
5155 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5156 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5157 << SpdyFramer::ErrorCodeToString(framer.error_code());
5159 } while (++flags != 0);
5162 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5163 uint8 flags = 0;
5164 do {
5165 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5167 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5168 SpdyFramer framer(spdy_version_);
5169 framer.set_visitor(&visitor);
5171 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5172 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5173 SetFrameFlags(frame.get(), flags, spdy_version_);
5175 if (flags != 0) {
5176 EXPECT_CALL(visitor, OnError(_));
5177 } else {
5178 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5181 framer.ProcessInput(frame->data(), frame->size());
5182 if (flags != 0) {
5183 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5184 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5185 framer.error_code())
5186 << SpdyFramer::ErrorCodeToString(framer.error_code());
5187 } else {
5188 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5189 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5190 << SpdyFramer::ErrorCodeToString(framer.error_code());
5192 } while (++flags != 0);
5195 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5196 uint8 flags = 0;
5197 do {
5198 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5200 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5201 SpdyFramer framer(spdy_version_);
5202 framer.set_visitor(&visitor);
5204 SpdyHeadersIR headers_ir(57);
5205 if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
5206 headers_ir.set_priority(3);
5207 headers_ir.set_has_priority(true);
5209 headers_ir.SetHeader("foo", "bar");
5210 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5211 uint8 set_flags = flags;
5212 if (IsSpdy4()) {
5213 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5214 // and implement framing.
5215 set_flags &= ~HEADERS_FLAG_PADDED;
5217 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5219 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5220 EXPECT_CALL(visitor, OnError(_));
5221 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5222 HEADERS_FLAG_END_HEADERS |
5223 HEADERS_FLAG_END_SEGMENT |
5224 HEADERS_FLAG_PADDED |
5225 HEADERS_FLAG_PRIORITY)) {
5226 EXPECT_CALL(visitor, OnError(_));
5227 } else {
5228 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5229 EXPECT_CALL(visitor, OnHeaders(57, // stream id
5230 true, // has priority?
5231 3, // priority
5232 flags & CONTROL_FLAG_FIN, // fin?
5233 (flags & HEADERS_FLAG_END_HEADERS) ||
5234 !IsSpdy4())); // end headers?
5235 } else {
5236 EXPECT_CALL(visitor, OnHeaders(57, false, 0,
5237 flags & CONTROL_FLAG_FIN,
5238 (flags & HEADERS_FLAG_END_HEADERS) ||
5239 !IsSpdy4()));
5241 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5242 .WillRepeatedly(testing::Return(true));
5243 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
5244 flags & HEADERS_FLAG_END_HEADERS)) {
5245 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5246 } else {
5247 // Do not close the stream if we are expecting a CONTINUATION frame.
5248 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5252 framer.ProcessInput(frame->data(), frame->size());
5253 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5254 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5255 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5256 framer.error_code())
5257 << SpdyFramer::ErrorCodeToString(framer.error_code());
5258 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5259 HEADERS_FLAG_END_HEADERS |
5260 HEADERS_FLAG_END_SEGMENT |
5261 HEADERS_FLAG_PADDED |
5262 HEADERS_FLAG_PRIORITY)) {
5263 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5264 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5265 framer.error_code())
5266 << SpdyFramer::ErrorCodeToString(framer.error_code());
5267 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5268 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5269 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5270 << SpdyFramer::ErrorCodeToString(framer.error_code());
5271 } else {
5272 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5273 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5274 << SpdyFramer::ErrorCodeToString(framer.error_code());
5276 } while (++flags != 0);
5279 TEST_P(SpdyFramerTest, PingFrameFlags) {
5280 uint8 flags = 0;
5281 do {
5282 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5284 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5285 SpdyFramer framer(spdy_version_);
5286 framer.set_visitor(&visitor);
5288 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5289 SetFrameFlags(frame.get(), flags, spdy_version_);
5291 if (spdy_version_ > SPDY3 &&
5292 flags == PING_FLAG_ACK) {
5293 EXPECT_CALL(visitor, OnPing(42, true));
5294 } else if (flags == 0) {
5295 EXPECT_CALL(visitor, OnPing(42, false));
5296 } else {
5297 EXPECT_CALL(visitor, OnError(_));
5300 framer.ProcessInput(frame->data(), frame->size());
5301 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5302 flags == 0) {
5303 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5304 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5305 << SpdyFramer::ErrorCodeToString(framer.error_code());
5306 } else {
5307 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5308 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5309 framer.error_code())
5310 << SpdyFramer::ErrorCodeToString(framer.error_code());
5312 } while (++flags != 0);
5315 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5316 uint8 flags = 0;
5317 do {
5318 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5320 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5321 SpdyFramer framer(spdy_version_);
5322 framer.set_visitor(&visitor);
5324 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5325 SpdyWindowUpdateIR(4, 1024)));
5326 SetFrameFlags(frame.get(), flags, spdy_version_);
5328 if (flags != 0) {
5329 EXPECT_CALL(visitor, OnError(_));
5330 } else {
5331 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5334 framer.ProcessInput(frame->data(), frame->size());
5335 if (flags != 0) {
5336 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5337 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5338 framer.error_code())
5339 << SpdyFramer::ErrorCodeToString(framer.error_code());
5340 } else {
5341 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5342 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5343 << SpdyFramer::ErrorCodeToString(framer.error_code());
5345 } while (++flags != 0);
5348 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5349 if (spdy_version_ <= SPDY3) {
5350 return;
5353 uint8 flags = 0;
5354 do {
5355 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5357 testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
5358 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5359 SpdyFramer framer(spdy_version_);
5360 framer.set_visitor(&visitor);
5361 framer.set_debug_visitor(&debug_visitor);
5363 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5365 SpdyPushPromiseIR push_promise(42, 57);
5366 push_promise.SetHeader("foo", "bar");
5367 scoped_ptr<SpdySerializedFrame> frame(
5368 framer.SerializePushPromise(push_promise));
5369 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5370 // and implement framing.
5371 SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
5373 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5374 EXPECT_CALL(visitor, OnError(_));
5375 } else {
5376 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5377 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5378 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5379 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5380 .WillRepeatedly(testing::Return(true));
5383 framer.ProcessInput(frame->data(), frame->size());
5384 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5385 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5386 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5387 framer.error_code())
5388 << SpdyFramer::ErrorCodeToString(framer.error_code());
5389 } else {
5390 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5391 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5392 << SpdyFramer::ErrorCodeToString(framer.error_code());
5394 } while (++flags != 0);
5397 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5398 if (spdy_version_ <= SPDY3) {
5399 return;
5402 uint8 flags = 0;
5403 do {
5404 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5406 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5407 testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
5408 SpdyFramer framer(spdy_version_);
5409 framer.set_visitor(&visitor);
5410 framer.set_debug_visitor(&debug_visitor);
5412 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5413 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5414 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false));
5415 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5416 .WillRepeatedly(testing::Return(true));
5418 SpdyHeadersIR headers_ir(42);
5419 headers_ir.SetHeader("foo", "bar");
5420 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5421 SetFrameFlags(frame0.get(), 0, spdy_version_);
5423 SpdyContinuationIR continuation(42);
5424 continuation.SetHeader("foo", "bar");
5425 scoped_ptr<SpdySerializedFrame> frame(
5426 framer.SerializeContinuation(continuation));
5427 SetFrameFlags(frame.get(), flags, spdy_version_);
5429 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5430 EXPECT_CALL(visitor, OnError(_));
5431 } else {
5432 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5433 EXPECT_CALL(visitor, OnContinuation(42,
5434 flags & HEADERS_FLAG_END_HEADERS));
5435 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5436 .WillRepeatedly(testing::Return(true));
5439 framer.ProcessInput(frame0->data(), frame0->size());
5440 framer.ProcessInput(frame->data(), frame->size());
5441 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5442 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5443 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5444 framer.error_code())
5445 << SpdyFramer::ErrorCodeToString(framer.error_code());
5446 } else {
5447 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5448 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5449 << SpdyFramer::ErrorCodeToString(framer.error_code());
5451 } while (++flags != 0);
5454 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5456 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5458 TEST_P(SpdyFramerTest, EmptySynStream) {
5459 if (!IsSpdy2() && !IsSpdy3()) {
5460 // SYN_STREAM not supported in SPDY>3.
5461 return;
5463 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5464 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5465 SpdyFramer framer(spdy_version_);
5466 framer.set_visitor(&visitor);
5467 framer.set_debug_visitor(&debug_visitor);
5469 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5471 SpdySynStreamIR syn_stream(1);
5472 syn_stream.set_priority(1);
5473 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5474 // Adjust size to remove the name/value block.
5475 SetFrameLength(
5476 frame.get(),
5477 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5478 spdy_version_);
5480 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5481 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5482 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5484 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5485 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5486 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5487 << SpdyFramer::ErrorCodeToString(framer.error_code());
5490 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5491 const uint32 kId = 0x020304;
5492 const uint32 kFlags = 0x01;
5493 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5495 SettingsFlagsAndId id_and_flags =
5496 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5497 EXPECT_EQ(kId, id_and_flags.id());
5498 EXPECT_EQ(kFlags, id_and_flags.flags());
5499 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5502 // Test handling of a RST_STREAM with out-of-bounds status codes.
5503 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5504 const unsigned char kRstStreamStatusTooLow = 0x00;
5505 const unsigned char kRstStreamStatusTooHigh = 0xff;
5506 const unsigned char kV3RstStreamInvalid[] = {
5507 0x80, spdy_version_ch_, 0x00, 0x03,
5508 0x00, 0x00, 0x00, 0x08,
5509 0x00, 0x00, 0x00, 0x01,
5510 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5512 const unsigned char kV4RstStreamInvalid[] = {
5513 0x00, 0x00, 0x04, 0x03,
5514 0x00, 0x00, 0x00, 0x00,
5515 0x01, 0x00, 0x00, 0x00,
5516 kRstStreamStatusTooLow
5519 const unsigned char kV3RstStreamNumStatusCodes[] = {
5520 0x80, spdy_version_ch_, 0x00, 0x03,
5521 0x00, 0x00, 0x00, 0x08,
5522 0x00, 0x00, 0x00, 0x01,
5523 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5525 const unsigned char kV4RstStreamNumStatusCodes[] = {
5526 0x00, 0x00, 0x04, 0x03,
5527 0x00, 0x00, 0x00, 0x00,
5528 0x01, 0x00, 0x00, 0x00,
5529 kRstStreamStatusTooHigh
5532 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5533 SpdyFramer framer(spdy_version_);
5534 framer.set_visitor(&visitor);
5536 if (IsSpdy4()) {
5537 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5538 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
5539 arraysize(kV4RstStreamInvalid));
5540 } else {
5541 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5542 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5543 arraysize(kV3RstStreamInvalid));
5545 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5546 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5547 << SpdyFramer::ErrorCodeToString(framer.error_code());
5550 framer.Reset();
5552 if (IsSpdy4()) {
5553 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5554 framer.ProcessInput(
5555 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
5556 arraysize(kV4RstStreamNumStatusCodes));
5557 } else {
5558 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5559 framer.ProcessInput(
5560 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5561 arraysize(kV3RstStreamNumStatusCodes));
5563 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5564 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5565 << SpdyFramer::ErrorCodeToString(framer.error_code());
5568 // Test handling of GOAWAY frames with out-of-bounds status code.
5569 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5570 if (spdy_version_ <= SPDY2) {
5571 return;
5573 SpdyFramer framer(spdy_version_);
5575 const unsigned char kV3FrameData[] = {
5576 0x80, spdy_version_ch_, 0x00, 0x07,
5577 0x00, 0x00, 0x00, 0x08,
5578 0x00, 0x00, 0x00, 0x01, // Stream Id
5579 0xff, 0xff, 0xff, 0xff, // Status
5581 const unsigned char kV4FrameData[] = {
5582 0x00, 0x00, 0x0a, 0x07,
5583 0x00, 0x00, 0x00, 0x00,
5584 0x00, 0x00, 0x00, 0x00, // Stream id
5585 0x01, 0xff, 0xff, 0xff, // Status
5586 0xff, 0x47, 0x41, // Opaque Description
5588 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5589 framer.set_visitor(&visitor);
5591 if (IsSpdy3()) {
5592 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5593 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5594 arraysize(kV3FrameData));
5595 } else {
5596 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5597 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5598 arraysize(kV4FrameData));
5600 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5601 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5602 << SpdyFramer::ErrorCodeToString(framer.error_code());
5605 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5606 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5607 const unsigned char kV2FrameData[] = {
5608 0x80, spdy_version_ch_, 0x00, 0x07,
5609 0x00, 0x00, 0x00, 0x04,
5610 0xff, 0xff, 0xff, 0xff,
5612 const unsigned char kV3FrameData[] = {
5613 0x80, spdy_version_ch_, 0x00, 0x07,
5614 0x00, 0x00, 0x00, 0x08,
5615 0xff, 0xff, 0xff, 0xff,
5616 0x00, 0x00, 0x00, 0x00,
5618 const unsigned char kV4FrameData[] = {
5619 0x00, 0x00, 0x08, 0x07,
5620 0x00, 0x00, 0x00, 0x00,
5621 0x00, 0xff, 0xff, 0xff,
5622 0xff, 0x00, 0x00, 0x00,
5623 0x00,
5626 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5627 SpdyFramer framer(spdy_version_);
5628 framer.set_visitor(&visitor);
5630 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5631 if (IsSpdy2()) {
5632 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5633 arraysize(kV2FrameData));
5634 } else if (IsSpdy3()) {
5635 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5636 arraysize(kV3FrameData));
5637 } else {
5638 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5639 arraysize(kV4FrameData));
5641 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5642 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5643 << SpdyFramer::ErrorCodeToString(framer.error_code());
5646 TEST_P(SpdyFramerTest, OnBlocked) {
5647 if (spdy_version_ <= SPDY3) {
5648 return;
5651 const SpdyStreamId kStreamId = 0;
5653 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5654 SpdyFramer framer(spdy_version_);
5655 framer.set_visitor(&visitor);
5657 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5659 SpdyBlockedIR blocked_ir(0);
5660 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5661 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5663 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5664 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5665 << SpdyFramer::ErrorCodeToString(framer.error_code());
5668 TEST_P(SpdyFramerTest, OnAltSvc) {
5669 if (spdy_version_ <= SPDY3) {
5670 return;
5673 const SpdyStreamId kStreamId = 1;
5675 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5676 SpdyFramer framer(spdy_version_);
5677 framer.set_visitor(&visitor);
5679 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5681 443,
5682 StringPiece("pid"),
5683 StringPiece("h1"),
5684 StringPiece("o1")));
5686 SpdyAltSvcIR altsvc_ir(1);
5687 altsvc_ir.set_max_age(10);
5688 altsvc_ir.set_port(443);
5689 altsvc_ir.set_protocol_id("pid");
5690 altsvc_ir.set_host("h1");
5691 altsvc_ir.set_origin("o1");
5692 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5693 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5694 altsvc_ir.protocol_id().length() +
5695 altsvc_ir.host().length() +
5696 altsvc_ir.origin().length());
5698 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5699 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5700 << SpdyFramer::ErrorCodeToString(framer.error_code());
5703 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5704 if (spdy_version_ <= SPDY3) {
5705 return;
5708 const SpdyStreamId kStreamId = 1;
5710 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5711 SpdyFramer framer(spdy_version_);
5712 framer.set_visitor(&visitor);
5714 EXPECT_CALL(visitor, OnAltSvc(kStreamId,
5716 443,
5717 StringPiece("pid"),
5718 StringPiece("h1"),
5719 StringPiece("")));
5721 SpdyAltSvcIR altsvc_ir(1);
5722 altsvc_ir.set_max_age(10);
5723 altsvc_ir.set_port(443);
5724 altsvc_ir.set_protocol_id("pid");
5725 altsvc_ir.set_host("h1");
5726 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5727 framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
5728 altsvc_ir.protocol_id().length() +
5729 altsvc_ir.host().length());
5731 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5732 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5733 << SpdyFramer::ErrorCodeToString(framer.error_code());
5736 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5737 if (spdy_version_ <= SPDY3) {
5738 return;
5741 const unsigned char kType = static_cast<unsigned char>(
5742 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
5744 TestSpdyVisitor visitor(spdy_version_);
5745 SpdyFramer framer(spdy_version_);
5746 framer.set_visitor(&visitor);
5748 const unsigned char kFrameDataLargePIDLen[] = {
5749 0x00, 0x00, 0x17, kType, 0x00,
5750 0x00, 0x00, 0x00, 0x03,
5751 0x00, 0x00, 0x00, 0x05,
5752 0x01, 0xbb, 0x00, 0x05, // Port = 443
5753 'p', 'i', 'd', '1', // Protocol-ID
5754 0x04, 'h', 'o', 's',
5755 't', 'o', 'r', 'i',
5756 'g', 'i', 'n',
5759 visitor.SimulateInFramer(kFrameDataLargePIDLen,
5760 sizeof(kFrameDataLargePIDLen));
5761 EXPECT_EQ(1, visitor.error_count_);
5762 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5763 visitor.framer_.error_code());
5767 TestSpdyVisitor visitor(spdy_version_);
5768 SpdyFramer framer(spdy_version_);
5769 framer.set_visitor(&visitor);
5770 const unsigned char kFrameDataPIDLenLargerThanFrame[] = {
5771 0x00, 0x00, 0x17, kType, 0x00,
5772 0x00, 0x00, 0x00, 0x03,
5773 0x00, 0x00, 0x00, 0x05,
5774 0x01, 0xbb, 0x00, 0x99, // Port = 443
5775 'p', 'i', 'd', '1', // Protocol-ID
5776 0x04, 'h', 'o', 's',
5777 't', 'o', 'r', 'i',
5778 'g', 'i', 'n',
5781 visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame,
5782 sizeof(kFrameDataPIDLenLargerThanFrame));
5783 EXPECT_EQ(1, visitor.error_count_);
5784 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5785 visitor.framer_.error_code());
5789 TestSpdyVisitor visitor(spdy_version_);
5790 SpdyFramer framer(spdy_version_);
5791 framer.set_visitor(&visitor);
5793 const unsigned char kFrameDataLargeHostLen[] = {
5794 0x00, 0x00, 0x17, kType, 0x00,
5795 0x00, 0x00, 0x00, 0x03,
5796 0x00, 0x00, 0x00, 0x05,
5797 0x01, 0xbb, 0x00, 0x04, // Port = 443
5798 'p', 'i', 'd', '1', // Protocol-ID
5799 0x0f, 'h', 'o', 's',
5800 't', 'o', 'r', 'i',
5801 'g', 'i', 'n',
5804 visitor.SimulateInFramer(kFrameDataLargeHostLen,
5805 sizeof(kFrameDataLargeHostLen));
5806 EXPECT_EQ(1, visitor.error_count_);
5807 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5808 visitor.framer_.error_code());
5812 TestSpdyVisitor visitor(spdy_version_);
5813 SpdyFramer framer(spdy_version_);
5814 framer.set_visitor(&visitor);
5815 const unsigned char kFrameDataSmallPIDLen[] = {
5816 0x00, 0x00, 0x17, kType, 0x00,
5817 0x00, 0x00, 0x00, 0x03,
5818 0x00, 0x00, 0x00, 0x05,
5819 0x01, 0xbb, 0x00, 0x01, // Port = 443
5820 'p', 'i', 'd', '1', // Protocol-ID
5821 0x04, 'h', 'o', 's',
5822 't', 'o', 'r', 'i',
5823 'g', 'i', 'n',
5826 visitor.SimulateInFramer(kFrameDataSmallPIDLen,
5827 sizeof(kFrameDataSmallPIDLen));
5828 EXPECT_EQ(1, visitor.error_count_);
5829 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5830 visitor.framer_.error_code());
5834 // Tests handling of ALTSVC frames delivered in small chunks.
5835 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5836 if (spdy_version_ <= SPDY3) {
5837 return;
5839 SpdyFramer framer(spdy_version_);
5840 SpdyAltSvcIR altsvc_ir(1);
5841 altsvc_ir.set_max_age(20);
5842 altsvc_ir.set_port(443);
5843 altsvc_ir.set_protocol_id("protocolid");
5844 altsvc_ir.set_host("hostname");
5846 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5847 TestSpdyVisitor visitor(spdy_version_);
5848 visitor.use_compression_ = false;
5850 // Read data in small chunks.
5851 size_t framed_data = 0;
5852 size_t unframed_data = control_frame->size();
5853 size_t kReadChunkSize = 5; // Read five bytes at a time.
5854 while (unframed_data > 0) {
5855 size_t to_read = std::min(kReadChunkSize, unframed_data);
5856 visitor.SimulateInFramer(
5857 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5858 to_read);
5859 unframed_data -= to_read;
5860 framed_data += to_read;
5862 EXPECT_EQ(0, visitor.error_count_);
5863 EXPECT_EQ(1, visitor.altsvc_count_);
5864 EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
5865 EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
5866 EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
5867 EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
5870 // Tests handling of PRIORITY frames.
5871 TEST_P(SpdyFramerTest, ReadPriority) {
5872 if (spdy_version_ <= SPDY3) {
5873 return;
5875 SpdyFramer framer(spdy_version_);
5876 SpdyPriorityIR priority(3, 1, 255, false);
5877 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5878 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5879 framer.set_visitor(&visitor);
5880 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5881 framer.ProcessInput(frame->data(), frame->size());
5883 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5884 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5885 << SpdyFramer::ErrorCodeToString(framer.error_code());
5886 // TODO(mlavan): once we actually maintain a priority tree,
5887 // check that state is adjusted correctly.
5890 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5891 if (spdy_version_ <= SPDY3) {
5892 return;
5894 SpdyFramer framer(spdy_version_);
5896 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5897 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5898 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5899 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5900 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5901 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5902 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5903 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5905 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5906 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5907 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5908 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5909 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5910 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5911 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5912 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5913 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5914 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5915 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5916 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5917 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5918 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5919 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5922 // Tests handling of PRIORITY frame with incorrect size.
5923 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5924 if (spdy_version_ <= SPDY3) {
5925 return;
5928 // PRIORITY frame of size 4, which isn't correct.
5929 const unsigned char kFrameData[] = {
5930 0x00, 0x00, 0x04, 0x02, 0x00,
5931 0x00, 0x00, 0x00, 0x03,
5932 0x00, 0x00, 0x00, 0x01,
5935 TestSpdyVisitor visitor(spdy_version_);
5936 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
5938 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
5939 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5940 visitor.framer_.error_code())
5941 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
5944 } // namespace net