Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob066722fadb60ecd23493b162884a6491b2081929
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 "net/spdy/spdy_framer.h"
7 #include <stdlib.h>
8 #include <string.h>
10 #include <algorithm>
11 #include <limits>
12 #include <memory>
13 #include <string>
14 #include <vector>
16 #include "base/compiler_specific.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "net/spdy/hpack/hpack_constants.h"
19 #include "net/spdy/mock_spdy_framer_visitor.h"
20 #include "net/spdy/spdy_frame_builder.h"
21 #include "net/spdy/spdy_frame_reader.h"
22 #include "net/spdy/spdy_protocol.h"
23 #include "net/spdy/spdy_test_utils.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/platform_test.h"
27 using std::string;
28 using testing::_;
30 namespace net {
32 namespace test {
34 static const size_t kMaxDecompressedSize = 1024;
36 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
37 public:
38 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
39 SpdyFrameType type,
40 size_t payload_len,
41 size_t frame_len));
43 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
44 SpdyFrameType type,
45 size_t frame_len));
48 class SpdyFramerTestUtil {
49 public:
50 // Decompress a single frame using the decompression context held by
51 // the SpdyFramer. The implemention is meant for use only in tests
52 // and will CHECK fail if the input is anything other than a single,
53 // well-formed compressed frame.
55 // Returns a new decompressed SpdyFrame.
56 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
57 SpdyFramer* framer, const SpdyFrameType& frame) {
58 DecompressionVisitor visitor(framer->protocol_version());
59 framer->set_visitor(&visitor);
60 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
61 CHECK_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer->state());
62 framer->set_visitor(NULL);
64 char* buffer = visitor.ReleaseBuffer();
65 CHECK(buffer != NULL);
66 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
67 SetFrameLength(decompressed_frame,
68 visitor.size() - framer->GetControlFrameHeaderSize(),
69 framer->protocol_version());
70 return decompressed_frame;
73 class DecompressionVisitor : public SpdyFramerVisitorInterface {
74 public:
75 explicit DecompressionVisitor(SpdyMajorVersion version)
76 : version_(version), size_(0), finished_(false) {}
78 void ResetBuffer() {
79 CHECK(buffer_.get() == NULL);
80 CHECK_EQ(0u, size_);
81 CHECK(!finished_);
82 buffer_.reset(new char[kMaxDecompressedSize]);
85 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
86 void OnDataFrameHeader(SpdyStreamId stream_id,
87 size_t length,
88 bool fin) override {
89 LOG(FATAL) << "Unexpected data frame header";
91 void OnStreamFrameData(SpdyStreamId stream_id,
92 const char* data,
93 size_t len,
94 bool fin) override {
95 LOG(FATAL);
98 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
99 LOG(FATAL);
102 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
103 const char* header_data,
104 size_t len) override {
105 CHECK(buffer_.get() != NULL);
106 CHECK_GE(kMaxDecompressedSize, size_ + len);
107 CHECK(!finished_);
108 if (len != 0) {
109 memcpy(buffer_.get() + size_, header_data, len);
110 size_ += len;
111 } else {
112 // Done.
113 finished_ = true;
115 return true;
118 void OnSynStream(SpdyStreamId stream_id,
119 SpdyStreamId associated_stream_id,
120 SpdyPriority priority,
121 bool fin,
122 bool unidirectional) override {
123 SpdyFramer framer(version_);
124 framer.set_enable_compression(false);
125 SpdySynStreamIR syn_stream(stream_id);
126 syn_stream.set_associated_to_stream_id(associated_stream_id);
127 syn_stream.set_priority(priority);
128 syn_stream.set_fin(fin);
129 syn_stream.set_unidirectional(unidirectional);
130 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
131 ResetBuffer();
132 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
133 size_ += framer.GetSynStreamMinimumSize();
136 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
137 SpdyFramer framer(version_);
138 framer.set_enable_compression(false);
139 SpdyHeadersIR headers(stream_id);
140 headers.set_fin(fin);
141 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
142 ResetBuffer();
143 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
144 size_ += framer.GetSynStreamMinimumSize();
147 void OnRstStream(SpdyStreamId stream_id,
148 SpdyRstStreamStatus status) override {
149 LOG(FATAL);
151 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
152 LOG(FATAL);
154 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
155 void OnSettingsEnd() override { LOG(FATAL); }
156 void OnGoAway(SpdyStreamId last_accepted_stream_id,
157 SpdyGoAwayStatus status) override {
158 LOG(FATAL);
161 void OnHeaders(SpdyStreamId stream_id,
162 bool has_priority,
163 SpdyPriority priority,
164 SpdyStreamId parent_stream_id,
165 bool exclusive,
166 bool fin,
167 bool end) override {
168 SpdyFramer framer(version_);
169 framer.set_enable_compression(false);
170 SpdyHeadersIR headers(stream_id);
171 headers.set_has_priority(has_priority);
172 headers.set_priority(priority);
173 headers.set_parent_stream_id(parent_stream_id);
174 headers.set_exclusive(exclusive);
175 headers.set_fin(fin);
176 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
177 ResetBuffer();
178 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
179 size_ += framer.GetHeadersMinimumSize();
182 void OnWindowUpdate(SpdyStreamId stream_id,
183 int delta_window_size) override {
184 LOG(FATAL);
187 void OnPushPromise(SpdyStreamId stream_id,
188 SpdyStreamId promised_stream_id,
189 bool end) override {
190 SpdyFramer framer(version_);
191 framer.set_enable_compression(false);
192 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
193 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
194 ResetBuffer();
195 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
196 size_ += framer.GetPushPromiseMinimumSize();
199 void OnContinuation(SpdyStreamId stream_id, bool end) override {
200 LOG(FATAL);
203 void OnPriority(SpdyStreamId stream_id,
204 SpdyStreamId parent_stream_id,
205 uint8 weight,
206 bool exclusive) override {
207 // Do nothing.
210 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
211 LOG(FATAL);
212 return false;
215 char* ReleaseBuffer() {
216 CHECK(finished_);
217 return buffer_.release();
220 size_t size() const {
221 CHECK(finished_);
222 return size_;
225 private:
226 SpdyMajorVersion version_;
227 scoped_ptr<char[]> buffer_;
228 size_t size_;
229 bool finished_;
231 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
234 private:
235 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
238 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
239 public SpdyFramerDebugVisitorInterface {
240 public:
241 // This is larger than our max frame size because header blocks that
242 // are too long can spill over into CONTINUATION frames.
243 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
245 explicit TestSpdyVisitor(SpdyMajorVersion version)
246 : framer_(version),
247 use_compression_(false),
248 error_count_(0),
249 syn_frame_count_(0),
250 syn_reply_frame_count_(0),
251 headers_frame_count_(0),
252 push_promise_frame_count_(0),
253 goaway_count_(0),
254 setting_count_(0),
255 settings_ack_sent_(0),
256 settings_ack_received_(0),
257 continuation_count_(0),
258 altsvc_count_(0),
259 priority_count_(0),
260 test_altsvc_ir_(0),
261 on_unknown_frame_result_(false),
262 last_window_update_stream_(0),
263 last_window_update_delta_(0),
264 last_push_promise_stream_(0),
265 last_push_promise_promised_stream_(0),
266 data_bytes_(0),
267 fin_frame_count_(0),
268 fin_opaque_data_(),
269 fin_flag_count_(0),
270 zero_length_data_frame_count_(0),
271 control_frame_header_data_count_(0),
272 zero_length_control_frame_header_data_count_(0),
273 data_frame_count_(0),
274 last_payload_len_(0),
275 last_frame_len_(0),
276 header_buffer_(new char[kDefaultHeaderBufferSize]),
277 header_buffer_length_(0),
278 header_buffer_size_(kDefaultHeaderBufferSize),
279 header_stream_id_(static_cast<SpdyStreamId>(-1)),
280 header_control_type_(DATA),
281 header_buffer_valid_(false) {}
283 void OnError(SpdyFramer* f) override {
284 LOG(INFO) << "SpdyFramer Error: "
285 << SpdyFramer::ErrorCodeToString(f->error_code());
286 ++error_count_;
289 void OnDataFrameHeader(SpdyStreamId stream_id,
290 size_t length,
291 bool fin) override {
292 ++data_frame_count_;
293 header_stream_id_ = stream_id;
296 void OnStreamFrameData(SpdyStreamId stream_id,
297 const char* data,
298 size_t len,
299 bool fin) override {
300 EXPECT_EQ(header_stream_id_, stream_id);
301 if (len == 0)
302 ++zero_length_data_frame_count_;
304 data_bytes_ += len;
305 LOG(INFO) << "OnStreamFrameData(" << stream_id << ", \"";
306 if (len > 0) {
307 for (size_t i = 0 ; i < len; ++i) {
308 LOG(INFO) << std::hex << (0xFF & static_cast<unsigned int>(data[i]))
309 << std::dec;
312 LOG(INFO) << "\", " << len << ")\n";
315 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
316 EXPECT_EQ(header_stream_id_, stream_id);
317 data_bytes_ += len;
318 LOG(INFO) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
321 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
322 const char* header_data,
323 size_t len) override {
324 ++control_frame_header_data_count_;
325 CHECK_EQ(header_stream_id_, stream_id);
326 if (len == 0) {
327 ++zero_length_control_frame_header_data_count_;
328 // Indicates end-of-header-block.
329 headers_.clear();
330 CHECK(header_buffer_valid_);
331 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
332 header_buffer_.get(), header_buffer_length_, &headers_);
333 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
334 << "Check failed: header_buffer_length_ == parsed_length "
335 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
336 return true;
338 const size_t available = header_buffer_size_ - header_buffer_length_;
339 if (len > available) {
340 header_buffer_valid_ = false;
341 return false;
343 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
344 header_buffer_length_ += len;
345 return true;
348 void OnSynStream(SpdyStreamId stream_id,
349 SpdyStreamId associated_stream_id,
350 SpdyPriority priority,
351 bool fin,
352 bool unidirectional) override {
353 ++syn_frame_count_;
354 if (framer_.protocol_version() > SPDY3) {
355 InitHeaderStreaming(HEADERS, stream_id);
356 } else {
357 InitHeaderStreaming(SYN_STREAM, stream_id);
359 if (fin) {
360 ++fin_flag_count_;
364 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
365 ++syn_reply_frame_count_;
366 if (framer_.protocol_version() > SPDY3) {
367 InitHeaderStreaming(HEADERS, stream_id);
368 } else {
369 InitHeaderStreaming(SYN_REPLY, stream_id);
371 if (fin) {
372 ++fin_flag_count_;
376 void OnRstStream(SpdyStreamId stream_id,
377 SpdyRstStreamStatus status) override {
378 ++fin_frame_count_;
381 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
382 if ((rst_stream_data != NULL) && (len > 0)) {
383 fin_opaque_data_ += string(rst_stream_data, len);
385 return true;
388 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
389 ++setting_count_;
392 void OnSettingsAck() override {
393 DCHECK_LT(SPDY3, framer_.protocol_version());
394 ++settings_ack_received_;
397 void OnSettingsEnd() override {
398 if (framer_.protocol_version() <= SPDY3) { return; }
399 ++settings_ack_sent_;
402 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
404 void OnGoAway(SpdyStreamId last_accepted_stream_id,
405 SpdyGoAwayStatus status) override {
406 ++goaway_count_;
409 void OnHeaders(SpdyStreamId stream_id,
410 bool has_priority,
411 SpdyPriority priority,
412 SpdyStreamId parent_stream_id,
413 bool exclusive,
414 bool fin,
415 bool end) override {
416 ++headers_frame_count_;
417 InitHeaderStreaming(HEADERS, stream_id);
418 if (fin) {
419 ++fin_flag_count_;
421 header_has_priority_ = has_priority;
422 header_parent_stream_id_ = parent_stream_id;
423 header_exclusive_ = exclusive;
426 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
427 last_window_update_stream_ = stream_id;
428 last_window_update_delta_ = delta_window_size;
431 void OnPushPromise(SpdyStreamId stream_id,
432 SpdyStreamId promised_stream_id,
433 bool end) override {
434 ++push_promise_frame_count_;
435 InitHeaderStreaming(PUSH_PROMISE, stream_id);
436 last_push_promise_stream_ = stream_id;
437 last_push_promise_promised_stream_ = promised_stream_id;
440 void OnContinuation(SpdyStreamId stream_id, bool end) override {
441 ++continuation_count_;
444 void OnAltSvc(SpdyStreamId stream_id,
445 StringPiece origin,
446 const SpdyAltSvcWireFormat::AlternativeServiceVector&
447 altsvc_vector) override {
448 test_altsvc_ir_.set_stream_id(stream_id);
449 if (origin.length() > 0) {
450 test_altsvc_ir_.set_origin(origin.as_string());
452 for (const SpdyAltSvcWireFormat::AlternativeService& altsvc :
453 altsvc_vector) {
454 test_altsvc_ir_.add_altsvc(altsvc);
456 ++altsvc_count_;
459 void OnPriority(SpdyStreamId stream_id,
460 SpdyStreamId parent_stream_id,
461 uint8 weight,
462 bool exclusive) override {
463 ++priority_count_;
466 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
467 DLOG(INFO) << "Unknown frame type " << frame_type;
468 return on_unknown_frame_result_;
471 void OnSendCompressedFrame(SpdyStreamId stream_id,
472 SpdyFrameType type,
473 size_t payload_len,
474 size_t frame_len) override {
475 last_payload_len_ = payload_len;
476 last_frame_len_ = frame_len;
479 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
480 SpdyFrameType type,
481 size_t frame_len) override {
482 last_frame_len_ = frame_len;
485 // Convenience function which runs a framer simulation with particular input.
486 void SimulateInFramer(const unsigned char* input, size_t size) {
487 framer_.set_enable_compression(use_compression_);
488 framer_.set_visitor(this);
489 size_t input_remaining = size;
490 const char* input_ptr = reinterpret_cast<const char*>(input);
491 while (input_remaining > 0 &&
492 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
493 // To make the tests more interesting, we feed random (and small) chunks
494 // into the framer. This simulates getting strange-sized reads from
495 // the socket.
496 const size_t kMaxReadSize = 32;
497 size_t bytes_read =
498 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
499 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
500 input_remaining -= bytes_processed;
501 input_ptr += bytes_processed;
505 void InitHeaderStreaming(SpdyFrameType header_control_type,
506 SpdyStreamId stream_id) {
507 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
508 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
509 header_control_type))) {
510 DLOG(FATAL) << "Attempted to init header streaming with "
511 << "invalid control frame type: "
512 << header_control_type;
514 memset(header_buffer_.get(), 0, header_buffer_size_);
515 header_buffer_length_ = 0;
516 header_stream_id_ = stream_id;
517 header_control_type_ = header_control_type;
518 header_buffer_valid_ = true;
519 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
522 // Override the default buffer size (16K). Call before using the framer!
523 void set_header_buffer_size(size_t header_buffer_size) {
524 header_buffer_size_ = header_buffer_size;
525 header_buffer_.reset(new char[header_buffer_size]);
528 // Largest control frame that the SPDY implementation sends, including the
529 // size of the header.
530 static size_t sent_control_frame_max_size() {
531 return SpdyFramer::kMaxControlFrameSize;
534 static size_t header_data_chunk_max_size() {
535 return SpdyFramer::kHeaderDataChunkMaxSize;
538 SpdyFramer framer_;
539 bool use_compression_;
541 // Counters from the visitor callbacks.
542 int error_count_;
543 int syn_frame_count_;
544 int syn_reply_frame_count_;
545 int headers_frame_count_;
546 int push_promise_frame_count_;
547 int goaway_count_;
548 int setting_count_;
549 int settings_ack_sent_;
550 int settings_ack_received_;
551 int continuation_count_;
552 int altsvc_count_;
553 int priority_count_;
554 SpdyAltSvcIR test_altsvc_ir_;
555 bool on_unknown_frame_result_;
556 SpdyStreamId last_window_update_stream_;
557 int last_window_update_delta_;
558 SpdyStreamId last_push_promise_stream_;
559 SpdyStreamId last_push_promise_promised_stream_;
560 int data_bytes_;
561 int fin_frame_count_; // The count of RST_STREAM type frames received.
562 string fin_opaque_data_;
563 int fin_flag_count_; // The count of frames with the FIN flag set.
564 int zero_length_data_frame_count_; // The count of zero-length data frames.
565 int control_frame_header_data_count_; // The count of chunks received.
566 // The count of zero-length control frame header data chunks received.
567 int zero_length_control_frame_header_data_count_;
568 int data_frame_count_;
569 size_t last_payload_len_;
570 size_t last_frame_len_;
572 // Header block streaming state:
573 scoped_ptr<char[]> header_buffer_;
574 size_t header_buffer_length_;
575 size_t header_buffer_size_;
576 SpdyStreamId header_stream_id_;
577 SpdyFrameType header_control_type_;
578 bool header_buffer_valid_;
579 SpdyHeaderBlock headers_;
580 bool header_has_priority_;
581 SpdyStreamId header_parent_stream_id_;
582 bool header_exclusive_;
585 class SpdyFramerPeer {
586 public:
587 static size_t ControlFrameBufferSize() {
588 return SpdyFramer::kControlFrameBufferSize;
590 static size_t GetNumberRequiredContinuationFrames(SpdyFramer* framer,
591 size_t size) {
592 return framer->GetNumberRequiredContinuationFrames(size);
596 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
597 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
598 const SpdyFramer& framer) {
599 SpdyFrameReader reader(frame->data(), frame->size());
600 if (framer.protocol_version() > SPDY3) {
601 reader.Seek(3); // Seek past the frame length.
602 } else {
603 reader.Seek(2); // Seek past the frame length.
605 SpdyFrameType frame_type;
606 if (framer.protocol_version() > SPDY3) {
607 uint8 serialized_type;
608 reader.ReadUInt8(&serialized_type);
609 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
610 serialized_type);
611 DCHECK_EQ(HEADERS, frame_type);
612 uint8 flags;
613 reader.ReadUInt8(&flags);
614 if (flags & HEADERS_FLAG_PRIORITY) {
615 frame_type = SYN_STREAM;
617 } else {
618 uint16 serialized_type;
619 reader.ReadUInt16(&serialized_type);
620 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
621 serialized_type);
622 DCHECK(frame_type == HEADERS ||
623 frame_type == SYN_STREAM) << frame_type;
626 if (frame_type == SYN_STREAM) {
627 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
628 frame->size() - framer.GetSynStreamMinimumSize());
629 } else {
630 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
631 frame->size() - framer.GetHeadersMinimumSize());
635 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
636 protected:
637 void SetUp() override {
638 spdy_version_ = GetParam();
639 spdy_version_ch_ = static_cast<unsigned char>(
640 SpdyConstants::SerializeMajorVersion(spdy_version_));
643 void CompareFrame(const string& description,
644 const SpdyFrame& actual_frame,
645 const unsigned char* expected,
646 const int expected_len) {
647 const unsigned char* actual =
648 reinterpret_cast<const unsigned char*>(actual_frame.data());
649 CompareCharArraysWithHexError(
650 description, actual, actual_frame.size(), expected, expected_len);
653 void CompareFrames(const string& description,
654 const SpdyFrame& expected_frame,
655 const SpdyFrame& actual_frame) {
656 CompareCharArraysWithHexError(
657 description,
658 reinterpret_cast<const unsigned char*>(expected_frame.data()),
659 expected_frame.size(),
660 reinterpret_cast<const unsigned char*>(actual_frame.data()),
661 actual_frame.size());
664 // Returns true if the two header blocks have equivalent content.
665 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
666 const SpdyHeaderBlock* actual) {
667 if (expected->size() != actual->size()) {
668 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
669 << actual->size() << ".";
670 return false;
672 for (SpdyHeaderBlock::const_iterator it = expected->begin();
673 it != expected->end();
674 ++it) {
675 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
676 if (it2 == actual->end()) {
677 LOG(ERROR) << "Expected header name '" << it->first << "'.";
678 return false;
680 if (it->second.compare(it2->second) != 0) {
681 LOG(ERROR) << "Expected header named '" << it->first
682 << "' to have a value of '" << it->second
683 << "'. The actual value received was '" << it2->second
684 << "'.";
685 return false;
688 return true;
691 bool IsSpdy2() { return spdy_version_ == SPDY2; }
692 bool IsSpdy3() { return spdy_version_ == SPDY3; }
693 bool IsHttp2() { return spdy_version_ == HTTP2; }
695 // Version of SPDY protocol to be used.
696 SpdyMajorVersion spdy_version_;
697 unsigned char spdy_version_ch_;
700 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, HTTP/2.
701 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
702 SpdyFramerTest,
703 ::testing::Values(SPDY2, SPDY3, HTTP2));
705 // Test that we ignore cookie where both name and value are empty.
706 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
707 if (spdy_version_ > SPDY3) {
708 // Not implemented for hpack.
709 return;
712 SpdyFramer framer(spdy_version_);
713 framer.set_enable_compression(true);
714 SpdyHeadersIR headers(1);
715 headers.set_priority(1);
716 headers.SetHeader("cookie",
717 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
718 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
719 EXPECT_TRUE(frame.get() != NULL);
721 TestSpdyVisitor visitor(spdy_version_);
722 visitor.use_compression_ = true;
723 visitor.SimulateInFramer(
724 reinterpret_cast<unsigned char*>(frame->data()),
725 frame->size());
727 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
728 EXPECT_FALSE(CompareHeaderBlocks(&headers.header_block(), &visitor.headers_));
729 EXPECT_EQ(1u, visitor.headers_.size());
730 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
733 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
734 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
735 SpdyFramer framer(spdy_version_);
736 framer.set_enable_compression(false);
738 // Encode the header block into a Headers frame.
739 SpdyHeadersIR headers(1);
740 headers.set_priority(1);
741 headers.SetHeader("alpha", "beta");
742 headers.SetHeader("gamma", "charlie");
743 headers.SetHeader("cookie", "key1=value1; key2=value2");
744 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
745 EXPECT_TRUE(frame.get() != NULL);
747 TestSpdyVisitor visitor(spdy_version_);
748 visitor.use_compression_ = false;
749 visitor.SimulateInFramer(
750 reinterpret_cast<unsigned char*>(frame->data()),
751 frame->size());
753 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
754 EXPECT_TRUE(CompareHeaderBlocks(&headers.header_block(), &visitor.headers_));
757 // Test that if there's not a full frame, we fail to parse it.
758 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
759 SpdyFramer framer(spdy_version_);
760 framer.set_enable_compression(false);
762 // Encode the header block into a Headers frame.
763 SpdyHeadersIR headers(1);
764 headers.set_priority(1);
765 headers.SetHeader("alpha", "beta");
766 headers.SetHeader("gamma", "charlie");
767 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
768 EXPECT_TRUE(frame.get() != NULL);
770 TestSpdyVisitor visitor(spdy_version_);
771 visitor.use_compression_ = false;
772 visitor.SimulateInFramer(
773 reinterpret_cast<unsigned char*>(frame->data()),
774 frame->size() - 2);
776 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
777 EXPECT_EQ(0u, visitor.headers_.size());
780 // Test that we can encode and decode stream dependency values in a header
781 // frame.
782 TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
783 if (spdy_version_ <= SPDY3) {
784 return;
786 SpdyFramer framer(spdy_version_);
787 framer.set_enable_compression(false);
789 const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
790 for (SpdyStreamId parent_stream_id : parent_stream_id_test_array) {
791 const bool exclusive_test_array[] = {true, false};
792 for (bool exclusive : exclusive_test_array) {
793 SpdyHeadersIR headers(1);
794 headers.set_has_priority(true);
795 headers.set_parent_stream_id(parent_stream_id);
796 headers.set_exclusive(exclusive);
797 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
798 EXPECT_TRUE(frame.get() != NULL);
800 TestSpdyVisitor visitor(spdy_version_);
801 visitor.use_compression_ = false;
802 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame->data()),
803 frame->size());
805 EXPECT_TRUE(visitor.header_has_priority_);
806 EXPECT_EQ(parent_stream_id, visitor.header_parent_stream_id_);
807 EXPECT_EQ(exclusive, visitor.header_exclusive_);
812 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
813 // (but don't crash).
814 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
815 if (spdy_version_ > SPDY3) {
816 return;
818 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
819 SpdyFramer framer(spdy_version_);
820 framer.set_visitor(&visitor);
822 SpdySynReplyIR syn_reply(0);
823 syn_reply.SetHeader("alpha", "beta");
824 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
825 ASSERT_TRUE(frame.get() != NULL);
827 // We shouldn't have to read the whole frame before we signal an error.
828 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
829 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
830 EXPECT_TRUE(framer.HasError());
831 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
832 << SpdyFramer::ErrorCodeToString(framer.error_code());
835 // Test that if we receive a HEADERS with stream ID zero, we signal an error
836 // (but don't crash).
837 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
838 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
839 SpdyFramer framer(spdy_version_);
840 framer.set_visitor(&visitor);
842 SpdyHeadersIR headers_ir(0);
843 headers_ir.SetHeader("alpha", "beta");
844 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
845 ASSERT_TRUE(frame.get() != NULL);
847 // We shouldn't have to read the whole frame before we signal an error.
848 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
849 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
850 EXPECT_TRUE(framer.HasError());
851 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
852 << SpdyFramer::ErrorCodeToString(framer.error_code());
855 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
856 // error (but don't crash).
857 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
858 if (spdy_version_ <= SPDY3) {
859 return;
862 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
863 SpdyFramer framer(spdy_version_);
864 framer.set_visitor(&visitor);
866 SpdyPushPromiseIR push_promise(0, 4);
867 push_promise.SetHeader("alpha", "beta");
868 scoped_ptr<SpdySerializedFrame> frame(
869 framer.SerializePushPromise(push_promise));
870 ASSERT_TRUE(frame.get() != NULL);
872 // We shouldn't have to read the whole frame before we signal an error.
873 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
874 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
875 EXPECT_TRUE(framer.HasError());
876 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
877 << SpdyFramer::ErrorCodeToString(framer.error_code());
880 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
881 // signal an error (but don't crash).
882 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
883 if (spdy_version_ <= SPDY3) {
884 return;
887 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
888 SpdyFramer framer(spdy_version_);
889 framer.set_visitor(&visitor);
891 SpdyPushPromiseIR push_promise(3, 0);
892 push_promise.SetHeader("alpha", "beta");
893 scoped_ptr<SpdySerializedFrame> frame(
894 framer.SerializePushPromise(push_promise));
895 ASSERT_TRUE(frame.get() != NULL);
897 // We shouldn't have to read the whole frame before we signal an error.
898 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
899 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
900 EXPECT_TRUE(framer.HasError());
901 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
902 << SpdyFramer::ErrorCodeToString(framer.error_code());
905 TEST_P(SpdyFramerTest, DuplicateHeader) {
906 if (spdy_version_ > SPDY3) {
907 // TODO(jgraettinger): Punting on this because we haven't determined
908 // whether duplicate HPACK headers other than Cookie are an error.
909 // If they are, this will need to be updated to use HpackOutputStream.
910 return;
912 SpdyFramer framer(spdy_version_);
913 // Frame builder with plentiful buffer size.
914 SpdyFrameBuilder frame(1024, spdy_version_);
915 if (spdy_version_ <= SPDY3) {
916 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
917 frame.WriteUInt32(3); // stream_id
918 frame.WriteUInt32(0); // associated stream id
919 frame.WriteUInt16(0); // Priority.
920 } else {
921 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
922 frame.WriteUInt32(framer.GetHighestPriority());
925 if (IsSpdy2()) {
926 frame.WriteUInt16(2); // Number of headers.
927 frame.WriteStringPiece16("name");
928 frame.WriteStringPiece16("value1");
929 frame.WriteStringPiece16("name");
930 frame.WriteStringPiece16("value2");
931 } else {
932 frame.WriteUInt32(2); // Number of headers.
933 frame.WriteStringPiece32("name");
934 frame.WriteStringPiece32("value1");
935 frame.WriteStringPiece32("name");
936 frame.WriteStringPiece32("value2");
938 // write the length
939 frame.RewriteLength(framer);
941 SpdyHeaderBlock new_headers;
942 framer.set_enable_compression(false);
943 scoped_ptr<SpdyFrame> control_frame(frame.take());
944 base::StringPiece serialized_headers =
945 GetSerializedHeaders(control_frame.get(), framer);
946 // This should fail because duplicate headers are verboten by the spec.
947 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
948 serialized_headers.size(),
949 &new_headers));
952 TEST_P(SpdyFramerTest, MultiValueHeader) {
953 SpdyFramer framer(spdy_version_);
954 // Frame builder with plentiful buffer size.
955 SpdyFrameBuilder frame(1024, spdy_version_);
956 if (spdy_version_ <= SPDY3) {
957 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
958 frame.WriteUInt32(3); // stream_id
959 frame.WriteUInt32(0); // associated stream id
960 frame.WriteUInt16(0); // Priority.
961 } else {
962 frame.BeginNewFrame(framer,
963 HEADERS,
964 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
966 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
967 frame.WriteUInt8(255); // Priority weight.
970 string value("value1\0value2", 13);
971 if (IsSpdy2()) {
972 frame.WriteUInt16(1); // Number of headers.
973 frame.WriteStringPiece16("name");
974 frame.WriteStringPiece16(value);
975 } else if (spdy_version_ > SPDY3) {
976 // TODO(jgraettinger): If this pattern appears again, move to test class.
977 SpdyHeaderBlock header_set;
978 header_set["name"] = value;
979 string buffer;
980 HpackEncoder encoder(ObtainHpackHuffmanTable());
981 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
982 frame.WriteBytes(&buffer[0], buffer.size());
983 } else {
984 frame.WriteUInt32(1); // Number of headers.
985 frame.WriteStringPiece32("name");
986 frame.WriteStringPiece32(value);
988 // write the length
989 frame.RewriteLength(framer);
991 framer.set_enable_compression(false);
992 scoped_ptr<SpdyFrame> control_frame(frame.take());
994 TestSpdyVisitor visitor(spdy_version_);
995 visitor.use_compression_ = false;
996 visitor.SimulateInFramer(
997 reinterpret_cast<unsigned char*>(control_frame->data()),
998 control_frame->size());
1000 EXPECT_THAT(visitor.headers_,
1001 testing::ElementsAre(testing::Pair("name", value)));
1004 TEST_P(SpdyFramerTest, BasicCompression) {
1005 if (spdy_version_ > SPDY3) {
1006 // Deflate compression doesn't apply to HPACK.
1007 return;
1009 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
1010 SpdyFramer framer(spdy_version_);
1011 framer.set_debug_visitor(visitor.get());
1012 SpdySynStreamIR syn_stream(1);
1013 syn_stream.set_priority(1);
1014 syn_stream.SetHeader("server", "SpdyServer 1.0");
1015 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1016 syn_stream.SetHeader("status", "200");
1017 syn_stream.SetHeader("version", "HTTP/1.1");
1018 syn_stream.SetHeader("content-type", "text/html");
1019 syn_stream.SetHeader("content-length", "12");
1020 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
1021 size_t uncompressed_size1 = visitor->last_payload_len_;
1022 size_t compressed_size1 =
1023 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1024 if (IsSpdy2()) {
1025 EXPECT_EQ(139u, uncompressed_size1);
1026 #if defined(USE_SYSTEM_ZLIB)
1027 EXPECT_EQ(155u, compressed_size1);
1028 #else // !defined(USE_SYSTEM_ZLIB)
1029 EXPECT_EQ(135u, compressed_size1);
1030 #endif // !defined(USE_SYSTEM_ZLIB)
1031 } else {
1032 EXPECT_EQ(165u, uncompressed_size1);
1033 #if defined(USE_SYSTEM_ZLIB)
1034 EXPECT_EQ(181u, compressed_size1);
1035 #else // !defined(USE_SYSTEM_ZLIB)
1036 EXPECT_EQ(117u, compressed_size1);
1037 #endif // !defined(USE_SYSTEM_ZLIB)
1039 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
1040 size_t uncompressed_size2 = visitor->last_payload_len_;
1041 size_t compressed_size2 =
1042 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1044 // Expect the second frame to be more compact than the first.
1045 EXPECT_LE(frame2->size(), frame1->size());
1047 // Decompress the first frame
1048 scoped_ptr<SpdyFrame> frame3(
1049 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
1051 // Decompress the second frame
1052 visitor.reset(new TestSpdyVisitor(spdy_version_));
1053 framer.set_debug_visitor(visitor.get());
1054 scoped_ptr<SpdyFrame> frame4(
1055 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1056 size_t uncompressed_size4 =
1057 frame4->size() - framer.GetSynStreamMinimumSize();
1058 size_t compressed_size4 =
1059 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1060 if (IsSpdy2()) {
1061 EXPECT_EQ(139u, uncompressed_size4);
1062 #if defined(USE_SYSTEM_ZLIB)
1063 EXPECT_EQ(149u, compressed_size4);
1064 #else // !defined(USE_SYSTEM_ZLIB)
1065 EXPECT_EQ(101u, compressed_size4);
1066 #endif // !defined(USE_SYSTEM_ZLIB)
1067 } else {
1068 EXPECT_EQ(165u, uncompressed_size4);
1069 #if defined(USE_SYSTEM_ZLIB)
1070 EXPECT_EQ(175u, compressed_size4);
1071 #else // !defined(USE_SYSTEM_ZLIB)
1072 EXPECT_EQ(102u, compressed_size4);
1073 #endif // !defined(USE_SYSTEM_ZLIB)
1076 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1077 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1078 EXPECT_EQ(compressed_size2, compressed_size4);
1080 // Expect frames 3 & 4 to be the same.
1081 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1083 // Expect frames 3 to be the same as a uncompressed frame created
1084 // from scratch.
1085 framer.set_enable_compression(false);
1086 scoped_ptr<SpdyFrame> uncompressed_frame(
1087 framer.SerializeSynStream(syn_stream));
1088 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1091 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1092 // See crbug.com/172383
1093 SpdyHeadersIR headers(1);
1094 headers.SetHeader("server", "SpdyServer 1.0");
1095 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1096 headers.SetHeader("status", "200");
1097 headers.SetHeader("version", "HTTP/1.1");
1098 headers.SetHeader("content-type", "text/html");
1099 headers.SetHeader("content-length", "12");
1100 headers.SetHeader("x-empty-header", "");
1102 SpdyFramer framer(spdy_version_);
1103 framer.set_enable_compression(true);
1104 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1107 TEST_P(SpdyFramerTest, Basic) {
1108 const unsigned char kV2Input[] = {
1109 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1110 0x00, 0x00, 0x00, 0x14,
1111 0x00, 0x00, 0x00, 0x01,
1112 0x00, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x01,
1114 0x00, 0x02, 'h', 'h',
1115 0x00, 0x02, 'v', 'v',
1117 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1118 0x00, 0x00, 0x00, 0x18,
1119 0x00, 0x00, 0x00, 0x01,
1120 0x00, 0x00, 0x00, 0x02,
1121 0x00, 0x02, 'h', '2',
1122 0x00, 0x02, 'v', '2',
1123 0x00, 0x02, 'h', '3',
1124 0x00, 0x02, 'v', '3',
1126 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1127 0x00, 0x00, 0x00, 0x0c,
1128 0xde, 0xad, 0xbe, 0xef,
1129 0xde, 0xad, 0xbe, 0xef,
1130 0xde, 0xad, 0xbe, 0xef,
1132 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1133 0x00, 0x00, 0x00, 0x0c,
1134 0x00, 0x00, 0x00, 0x03,
1135 0x00, 0x00, 0x00, 0x00,
1136 0x00, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1139 0x00, 0x00, 0x00, 0x08,
1140 0xde, 0xad, 0xbe, 0xef,
1141 0xde, 0xad, 0xbe, 0xef,
1143 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1144 0x00, 0x00, 0x00, 0x04,
1145 0xde, 0xad, 0xbe, 0xef,
1147 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1148 0x00, 0x00, 0x00, 0x08,
1149 0x00, 0x00, 0x00, 0x01,
1150 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1152 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1153 0x00, 0x00, 0x00, 0x00,
1155 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1156 0x00, 0x00, 0x00, 0x08,
1157 0x00, 0x00, 0x00, 0x03,
1158 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1161 const unsigned char kV3Input[] = {
1162 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1163 0x00, 0x00, 0x00, 0x1a,
1164 0x00, 0x00, 0x00, 0x01,
1165 0x00, 0x00, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x01, 0x00, 0x00,
1168 0x00, 0x02, 'h', 'h',
1169 0x00, 0x00, 0x00, 0x02,
1170 'v', 'v',
1172 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1173 0x00, 0x00, 0x00, 0x20,
1174 0x00, 0x00, 0x00, 0x01,
1175 0x00, 0x00, 0x00, 0x02,
1176 0x00, 0x00, 0x00, 0x02,
1177 'h', '2',
1178 0x00, 0x00, 0x00, 0x02,
1179 'v', '2', 0x00, 0x00,
1180 0x00, 0x02, 'h', '3',
1181 0x00, 0x00, 0x00, 0x02,
1182 'v', '3',
1184 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1185 0x00, 0x00, 0x00, 0x0c,
1186 0xde, 0xad, 0xbe, 0xef,
1187 0xde, 0xad, 0xbe, 0xef,
1188 0xde, 0xad, 0xbe, 0xef,
1190 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1191 0x00, 0x00, 0x00, 0x0e,
1192 0x00, 0x00, 0x00, 0x03,
1193 0x00, 0x00, 0x00, 0x00,
1194 0x00, 0x00, 0x00, 0x00,
1195 0x00, 0x00,
1197 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1198 0x00, 0x00, 0x00, 0x08,
1199 0xde, 0xad, 0xbe, 0xef,
1200 0xde, 0xad, 0xbe, 0xef,
1202 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1203 0x00, 0x00, 0x00, 0x04,
1204 0xde, 0xad, 0xbe, 0xef,
1206 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1207 0x00, 0x00, 0x00, 0x08,
1208 0x00, 0x00, 0x00, 0x01,
1209 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1211 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1212 0x00, 0x00, 0x00, 0x00,
1214 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1215 0x00, 0x00, 0x00, 0x08,
1216 0x00, 0x00, 0x00, 0x03,
1217 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1220 // SYN_STREAM doesn't exist in HTTP/2, so instead we send
1221 // HEADERS frames with PRIORITY and END_HEADERS set.
1222 const unsigned char kH2Input[] = {
1223 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1224 0x24, 0x00, 0x00, 0x00,
1225 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1226 0x00, 0x82, // :method: GET
1228 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1229 0x04, 0x00, 0x00, 0x00, // Stream 1
1230 0x01, 0x8c, // :status: 200
1232 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1233 0x00, 0x00, 0x00, 0x00,
1234 0x01, 0xde, 0xad, 0xbe,
1235 0xef, 0xde, 0xad, 0xbe,
1236 0xef, 0xde, 0xad, 0xbe,
1237 0xef,
1239 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1240 0x24, 0x00, 0x00, 0x00,
1241 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1242 0x00, 0x82, // :method: GET
1244 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1245 0x00, 0x00, 0x00, 0x00,
1246 0x03, 0xde, 0xad, 0xbe,
1247 0xef, 0xde, 0xad, 0xbe,
1248 0xef,
1250 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1251 0x00, 0x00, 0x00, 0x00,
1252 0x01, 0xde, 0xad, 0xbe,
1253 0xef,
1255 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1256 0x00, 0x00, 0x00, 0x00,
1257 0x01, 0x00, 0x00, 0x00,
1258 0x08, // RST_STREAM_CANCEL
1260 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1261 0x00, 0x00, 0x00, 0x00,
1262 0x03,
1264 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1265 0x00, 0x00, 0x00, 0x00,
1266 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1267 0x08, 0x52, 0x45, 0x53, // opaque data
1268 0x45, 0x54, 0x53, 0x54,
1269 0x52, 0x45, 0x41, 0x4d,
1272 TestSpdyVisitor visitor(spdy_version_);
1273 if (IsSpdy2()) {
1274 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1275 } else if (IsSpdy3()) {
1276 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1277 } else {
1278 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1281 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1282 EXPECT_EQ(24, visitor.data_bytes_);
1283 EXPECT_EQ(0, visitor.error_count_);
1284 EXPECT_EQ(2, visitor.fin_frame_count_);
1286 if (IsHttp2()) {
1287 EXPECT_EQ(3, visitor.headers_frame_count_);
1288 EXPECT_EQ(0, visitor.syn_frame_count_);
1289 base::StringPiece reset_stream = "RESETSTREAM";
1290 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1291 } else {
1292 EXPECT_EQ(1, visitor.headers_frame_count_);
1293 EXPECT_EQ(2, visitor.syn_frame_count_);
1294 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1297 EXPECT_EQ(0, visitor.fin_flag_count_);
1298 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1299 EXPECT_EQ(4, visitor.data_frame_count_);
1300 visitor.fin_opaque_data_.clear();
1303 // Test that the FIN flag on a data frame signifies EOF.
1304 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1305 const unsigned char kV2Input[] = {
1306 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1307 0x00, 0x00, 0x00, 0x14,
1308 0x00, 0x00, 0x00, 0x01,
1309 0x00, 0x00, 0x00, 0x00,
1310 0x00, 0x00, 0x00, 0x01,
1311 0x00, 0x02, 'h', 'h',
1312 0x00, 0x02, 'v', 'v',
1314 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1315 0x00, 0x00, 0x00, 0x10,
1316 0x00, 0x00, 0x00, 0x01,
1317 0x00, 0x00, 0x00, 0x01,
1318 0x00, 0x02, 'a', 'a',
1319 0x00, 0x02, 'b', 'b',
1321 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1322 0x00, 0x00, 0x00, 0x0c,
1323 0xde, 0xad, 0xbe, 0xef,
1324 0xde, 0xad, 0xbe, 0xef,
1325 0xde, 0xad, 0xbe, 0xef,
1327 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1328 0x01, 0x00, 0x00, 0x04,
1329 0xde, 0xad, 0xbe, 0xef,
1331 const unsigned char kV3Input[] = {
1332 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1333 0x00, 0x00, 0x00, 0x1a,
1334 0x00, 0x00, 0x00, 0x01,
1335 0x00, 0x00, 0x00, 0x00,
1336 0x00, 0x00, 0x00, 0x00,
1337 0x00, 0x01, 0x00, 0x00,
1338 0x00, 0x02, 'h', 'h',
1339 0x00, 0x00, 0x00, 0x02,
1340 'v', 'v',
1342 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1343 0x00, 0x00, 0x00, 0x14,
1344 0x00, 0x00, 0x00, 0x01,
1345 0x00, 0x00, 0x00, 0x01,
1346 0x00, 0x00, 0x00, 0x02,
1347 'a', 'a', 0x00, 0x00,
1348 0x00, 0x02, 'b', 'b',
1350 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1351 0x00, 0x00, 0x00, 0x0c,
1352 0xde, 0xad, 0xbe, 0xef,
1353 0xde, 0xad, 0xbe, 0xef,
1354 0xde, 0xad, 0xbe, 0xef,
1356 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1357 0x01, 0x00, 0x00, 0x04,
1358 0xde, 0xad, 0xbe, 0xef,
1361 // SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
1362 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1363 const unsigned char kH2Input[] = {
1364 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1365 0x24, 0x00, 0x00, 0x00, // Stream 1
1366 0x01, 0x00, 0x00, 0x00, // Priority 0
1367 0x00, 0x82, // :method: GET
1369 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1370 0x04, 0x00, 0x00, 0x00, // Stream 1
1371 0x01, 0x8c, // :status: 200
1373 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1374 0x00, 0x00, 0x00, 0x00,
1375 0x01, 0xde, 0xad, 0xbe,
1376 0xef, 0xde, 0xad, 0xbe,
1377 0xef, 0xde, 0xad, 0xbe,
1378 0xef,
1380 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1381 0x01, 0x00, 0x00, 0x00,
1382 0x01, 0xde, 0xad, 0xbe,
1383 0xef,
1386 TestSpdyVisitor visitor(spdy_version_);
1387 if (IsSpdy2()) {
1388 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1389 } else if (IsSpdy3()) {
1390 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1391 } else {
1392 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1395 EXPECT_EQ(0, visitor.error_count_);
1396 if (IsHttp2()) {
1397 EXPECT_EQ(0, visitor.syn_frame_count_);
1398 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1399 EXPECT_EQ(2, visitor.headers_frame_count_);
1400 } else {
1401 EXPECT_EQ(1, visitor.syn_frame_count_);
1402 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1403 EXPECT_EQ(0, visitor.headers_frame_count_);
1405 EXPECT_EQ(16, visitor.data_bytes_);
1406 EXPECT_EQ(0, visitor.fin_frame_count_);
1407 EXPECT_EQ(0, visitor.fin_flag_count_);
1408 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1409 EXPECT_EQ(2, visitor.data_frame_count_);
1412 // Test that the FIN flag on a SYN reply frame signifies EOF.
1413 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1414 const unsigned char kV2Input[] = {
1415 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1416 0x01, 0x00, 0x00, 0x00,
1417 0x14, 0x00, 0x00, 0x00,
1418 0x01, 0x00, 0x00, 0x00,
1419 0x00, 0x00, 0x00, 0x00,
1420 0x01, 0x00, 0x02, 'h',
1421 'h', 0x00, 0x02, 'v',
1422 'v',
1424 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1425 0x02, 0x01, 0x00, 0x00,
1426 0x10, 0x00, 0x00, 0x00,
1427 0x01, 0x00, 0x00, 0x00,
1428 0x01, 0x00, 0x02, 'a',
1429 'a', 0x00, 0x02, 'b',
1430 'b',
1432 const unsigned char kV3Input[] = {
1433 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1434 0x01, 0x00, 0x00, 0x00,
1435 0x1a, 0x00, 0x00, 0x00,
1436 0x01, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00,
1438 0x00, 0x00, 0x01, 0x00,
1439 0x00, 0x00, 0x02, 'h',
1440 'h', 0x00, 0x00, 0x00,
1441 0x02, 'v', 'v',
1443 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1444 0x02, 0x01, 0x00, 0x00,
1445 0x14, 0x00, 0x00, 0x00,
1446 0x01, 0x00, 0x00, 0x00,
1447 0x01, 0x00, 0x00, 0x00,
1448 0x02, 'a', 'a', 0x00,
1449 0x00, 0x00, 0x02, 'b',
1450 'b',
1453 // SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
1454 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1455 const unsigned char kH2Input[] = {
1456 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1457 0x24, 0x00, 0x00, 0x00,
1458 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1459 0x00, 0x82, // :method: GET
1461 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1462 0x05, 0x00, 0x00, 0x00,
1463 0x01, 0x8c, // Stream 1, :status: 200
1466 TestSpdyVisitor visitor(spdy_version_);
1467 if (IsSpdy2()) {
1468 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1469 } else if (IsSpdy3()) {
1470 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1471 } else {
1472 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1475 EXPECT_EQ(0, visitor.error_count_);
1476 if (IsHttp2()) {
1477 EXPECT_EQ(0, visitor.syn_frame_count_);
1478 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1479 EXPECT_EQ(2, visitor.headers_frame_count_);
1480 } else {
1481 EXPECT_EQ(1, visitor.syn_frame_count_);
1482 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1483 EXPECT_EQ(0, visitor.headers_frame_count_);
1485 EXPECT_EQ(0, visitor.data_bytes_);
1486 EXPECT_EQ(0, visitor.fin_frame_count_);
1487 EXPECT_EQ(1, visitor.fin_flag_count_);
1488 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1489 EXPECT_EQ(0, visitor.data_frame_count_);
1492 TEST_P(SpdyFramerTest, HeaderCompression) {
1493 if (spdy_version_ > SPDY3) {
1494 // Deflate compression doesn't apply to HPACK.
1495 return;
1497 SpdyFramer send_framer(spdy_version_);
1498 SpdyFramer recv_framer(spdy_version_);
1500 send_framer.set_enable_compression(true);
1501 recv_framer.set_enable_compression(true);
1503 const char kHeader1[] = "header1";
1504 const char kHeader2[] = "header2";
1505 const char kHeader3[] = "header3";
1506 const char kValue1[] = "value1";
1507 const char kValue2[] = "value2";
1508 const char kValue3[] = "value3";
1510 // SYN_STREAM #1
1511 SpdyHeaderBlock block;
1512 block[kHeader1] = kValue1;
1513 block[kHeader2] = kValue2;
1514 SpdySynStreamIR syn_ir_1(1);
1515 syn_ir_1.set_header_block(block);
1516 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1517 EXPECT_TRUE(syn_frame_1.get() != NULL);
1519 // SYN_STREAM #2
1520 block[kHeader3] = kValue3;
1521 SpdySynStreamIR syn_stream(3);
1522 syn_stream.set_header_block(block);
1523 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1524 EXPECT_TRUE(syn_frame_2.get() != NULL);
1526 // Now start decompressing
1527 scoped_ptr<SpdyFrame> decompressed;
1528 scoped_ptr<SpdyFrame> uncompressed;
1529 base::StringPiece serialized_headers;
1530 SpdyHeaderBlock decompressed_headers;
1532 // Decompress SYN_STREAM #1
1533 decompressed.reset(
1534 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1535 EXPECT_TRUE(decompressed.get() != NULL);
1536 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1537 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1538 serialized_headers.size(),
1539 &decompressed_headers));
1540 EXPECT_EQ(2u, decompressed_headers.size());
1541 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1542 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1544 // Decompress SYN_STREAM #2
1545 decompressed.reset(
1546 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1547 EXPECT_TRUE(decompressed.get() != NULL);
1548 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1549 decompressed_headers.clear();
1550 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1551 serialized_headers.size(),
1552 &decompressed_headers));
1553 EXPECT_EQ(3u, decompressed_headers.size());
1554 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1555 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1556 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1559 // Verify we can decompress the stream even if handed over to the
1560 // framer 1 byte at a time.
1561 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1562 SpdyFramer send_framer(spdy_version_);
1564 send_framer.set_enable_compression(true);
1566 const char kHeader1[] = "header1";
1567 const char kHeader2[] = "header2";
1568 const char kValue1[] = "value1";
1569 const char kValue2[] = "value2";
1571 SpdyHeadersIR headers(1);
1572 headers.SetHeader(kHeader1, kValue1);
1573 headers.SetHeader(kHeader2, kValue2);
1574 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1575 EXPECT_TRUE(headers_frame.get() != NULL);
1577 const char bytes[] = "this is a test test test test test!";
1578 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1579 data_ir.set_fin(true);
1580 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1581 EXPECT_TRUE(send_frame.get() != NULL);
1583 // Run the inputs through the framer.
1584 TestSpdyVisitor visitor(spdy_version_);
1585 visitor.use_compression_ = true;
1586 const unsigned char* data;
1587 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1588 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1589 visitor.SimulateInFramer(data + idx, 1);
1590 ASSERT_EQ(0, visitor.error_count_);
1592 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1593 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1594 visitor.SimulateInFramer(data + idx, 1);
1595 ASSERT_EQ(0, visitor.error_count_);
1598 EXPECT_EQ(0, visitor.error_count_);
1599 EXPECT_EQ(0, visitor.syn_frame_count_);
1600 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1601 EXPECT_EQ(1, visitor.headers_frame_count_);
1602 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1603 EXPECT_EQ(0, visitor.fin_frame_count_);
1604 EXPECT_EQ(0, visitor.fin_flag_count_);
1605 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1606 EXPECT_EQ(1, visitor.data_frame_count_);
1609 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1610 SpdyFramer framer(spdy_version_);
1611 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1612 SpdyWindowUpdateIR(1, 0x12345678)));
1614 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1615 const unsigned char kV3FrameData[] = { // Also applies for V2.
1616 0x80, spdy_version_ch_, 0x00, 0x09,
1617 0x00, 0x00, 0x00, 0x08,
1618 0x00, 0x00, 0x00, 0x01,
1619 0x12, 0x34, 0x56, 0x78
1621 const unsigned char kH2FrameData[] = {
1622 0x00, 0x00, 0x04, 0x08,
1623 0x00, 0x00, 0x00, 0x00,
1624 0x01, 0x12, 0x34, 0x56,
1625 0x78
1628 if (IsHttp2()) {
1629 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1630 } else {
1631 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1635 TEST_P(SpdyFramerTest, CreateDataFrame) {
1636 SpdyFramer framer(spdy_version_);
1639 const char kDescription[] = "'hello' data frame, no FIN";
1640 const unsigned char kV3FrameData[] = { // Also applies for V2.
1641 0x00, 0x00, 0x00, 0x01,
1642 0x00, 0x00, 0x00, 0x05,
1643 'h', 'e', 'l', 'l',
1646 const unsigned char kH2FrameData[] = {0x00,
1647 0x00,
1648 0x05,
1649 0x00,
1650 0x00,
1651 0x00,
1652 0x00,
1653 0x00,
1654 0x01,
1655 'h',
1656 'e',
1657 'l',
1658 'l',
1659 'o'};
1660 const char bytes[] = "hello";
1662 SpdyDataIR data_ir(1, bytes);
1663 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1664 if (IsHttp2()) {
1665 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1666 } else {
1667 CompareFrame(
1668 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1671 SpdyDataIR data_header_ir(1);
1672 data_header_ir.SetDataShallow(bytes);
1673 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1674 data_header_ir));
1675 CompareCharArraysWithHexError(
1676 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1677 framer.GetDataFrameMinimumSize(),
1678 IsHttp2() ? kH2FrameData : kV3FrameData,
1679 framer.GetDataFrameMinimumSize());
1683 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1684 const unsigned char kV3FrameData[] = { // Also applies for V2.
1685 0x00, 0x00, 0x00, 0x01,
1686 0x00, 0x00, 0x00, 0x05,
1687 'h', 'e', 'l', 'l',
1691 const unsigned char kH2FrameData[] = {
1692 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1693 0x08, 0x00, 0x00, 0x00,
1694 0x01, 0xf7, // Pad length field.
1695 'h', 'e', 'l', 'l', // Data
1696 'o',
1697 // Padding of 247 0x00(s).
1698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1720 const char bytes[] = "hello";
1722 SpdyDataIR data_ir(1, bytes);
1723 // 247 zeros and the pad length field make the overall padding to be 248
1724 // bytes.
1725 data_ir.set_padding_len(248);
1726 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1727 if (IsHttp2()) {
1728 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1729 } else {
1730 CompareFrame(
1731 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1734 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1735 CompareCharArraysWithHexError(
1736 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1737 framer.GetDataFrameMinimumSize(),
1738 IsHttp2() ? kH2FrameData : kV3FrameData,
1739 framer.GetDataFrameMinimumSize());
1743 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1744 const unsigned char kV3FrameData[] = { // Also applies for V2.
1745 0x00, 0x00, 0x00, 0x01,
1746 0x00, 0x00, 0x00, 0x05,
1747 'h', 'e', 'l', 'l',
1751 const unsigned char kH2FrameData[] = {
1752 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1753 0x08, 0x00, 0x00, 0x00,
1754 0x01, 0x07, // Pad length field.
1755 'h', 'e', 'l', 'l', // Data
1756 'o',
1757 0x00, 0x00, 0x00, 0x00, // Padding
1758 0x00, 0x00, 0x00
1760 const char bytes[] = "hello";
1762 SpdyDataIR data_ir(1, bytes);
1763 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1764 data_ir.set_padding_len(8);
1765 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1766 if (IsHttp2()) {
1767 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1768 } else {
1769 CompareFrame(
1770 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1775 const char kDescription[] =
1776 "'hello' data frame with 1 byte padding, no FIN";
1777 const unsigned char kV3FrameData[] = { // Also applies for V2.
1778 0x00, 0x00, 0x00, 0x01,
1779 0x00, 0x00, 0x00, 0x05,
1780 'h', 'e', 'l', 'l',
1784 const unsigned char kH2FrameData[] = {
1785 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1786 0x08, 0x00, 0x00, 0x00,
1787 0x01, 0x00, // Pad length field.
1788 'h', 'e', 'l', 'l', // Data
1789 'o',
1791 const char bytes[] = "hello";
1793 SpdyDataIR data_ir(1, bytes);
1794 // The pad length field itself is used for the 1-byte padding and no padding
1795 // payload is needed.
1796 data_ir.set_padding_len(1);
1797 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1798 if (IsHttp2()) {
1799 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1800 } else {
1801 CompareFrame(
1802 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1805 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1806 CompareCharArraysWithHexError(
1807 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1808 framer.GetDataFrameMinimumSize(),
1809 IsHttp2() ? kH2FrameData : kV3FrameData,
1810 framer.GetDataFrameMinimumSize());
1814 const char kDescription[] = "Data frame with negative data byte, no FIN";
1815 const unsigned char kV3FrameData[] = { // Also applies for V2.
1816 0x00, 0x00, 0x00, 0x01,
1817 0x00, 0x00, 0x00, 0x01,
1818 0xff
1820 const unsigned char kH2FrameData[] = {
1821 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff};
1822 SpdyDataIR data_ir(1, "\xff");
1823 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1824 if (IsHttp2()) {
1825 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1826 } else {
1827 CompareFrame(
1828 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1833 const char kDescription[] = "'hello' data frame, with FIN";
1834 const unsigned char kV3FrameData[] = { // Also applies for V2.
1835 0x00, 0x00, 0x00, 0x01,
1836 0x01, 0x00, 0x00, 0x05,
1837 'h', 'e', 'l', 'l',
1840 const unsigned char kH2FrameData[] = {
1841 0x00, 0x00, 0x05, 0x00,
1842 0x01, 0x00, 0x00, 0x00,
1843 0x01, 'h', 'e', 'l',
1844 'l', 'o'
1846 SpdyDataIR data_ir(1, "hello");
1847 data_ir.set_fin(true);
1848 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1849 if (IsHttp2()) {
1850 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1851 } else {
1852 CompareFrame(
1853 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1858 const char kDescription[] = "Empty data frame";
1859 const unsigned char kV3FrameData[] = { // Also applies for V2.
1860 0x00, 0x00, 0x00, 0x01,
1861 0x00, 0x00, 0x00, 0x00,
1863 const unsigned char kH2FrameData[] = {
1864 0x00, 0x00, 0x00, 0x00,
1865 0x00, 0x00, 0x00, 0x00,
1866 0x01,
1868 SpdyDataIR data_ir(1, "");
1869 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1870 if (IsHttp2()) {
1871 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1872 } else {
1873 CompareFrame(
1874 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1877 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1878 CompareCharArraysWithHexError(
1879 kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
1880 framer.GetDataFrameMinimumSize(),
1881 IsHttp2() ? kH2FrameData : kV3FrameData,
1882 framer.GetDataFrameMinimumSize());
1886 const char kDescription[] = "Data frame with max stream ID";
1887 const unsigned char kV3FrameData[] = { // Also applies for V2.
1888 0x7f, 0xff, 0xff, 0xff,
1889 0x01, 0x00, 0x00, 0x05,
1890 'h', 'e', 'l', 'l',
1893 const unsigned char kH2FrameData[] = {
1894 0x00, 0x00, 0x05, 0x00,
1895 0x01, 0x7f, 0xff, 0xff,
1896 0xff, 'h', 'e', 'l',
1897 'l', 'o'
1899 SpdyDataIR data_ir(0x7fffffff, "hello");
1900 data_ir.set_fin(true);
1901 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1902 if (IsHttp2()) {
1903 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
1904 } else {
1905 CompareFrame(
1906 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1910 if (!IsHttp2()) {
1911 // This test does not apply to HTTP/2 because the max frame size is smaller
1912 // than 4MB.
1913 const char kDescription[] = "Large data frame";
1914 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1915 const string kData(kDataSize, 'A');
1916 const unsigned char kFrameHeader[] = {
1917 0x00, 0x00, 0x00, 0x01,
1918 0x01, 0x40, 0x00, 0x00,
1921 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1922 scoped_ptr<unsigned char[]> expected_frame_data(
1923 new unsigned char[kFrameSize]);
1924 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1925 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1927 SpdyDataIR data_ir(1, kData);
1928 data_ir.set_fin(true);
1929 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1930 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1934 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1935 if (!IsSpdy2() && !IsSpdy3()) {
1936 // SYN_STREAM unsupported in SPDY>3
1937 return;
1939 SpdyFramer framer(spdy_version_);
1940 framer.set_enable_compression(false);
1943 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1945 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1946 const unsigned char kV2FrameData[] = {
1947 0x80, spdy_version_ch_, 0x00, 0x01,
1948 0x00, 0x00, 0x00, 0x20,
1949 0x00, 0x00, 0x00, 0x01,
1950 0x00, 0x00, 0x00, 0x00,
1951 kPri, 0x00, 0x00, 0x02,
1952 0x00, 0x03, 'b', 'a',
1953 'r', 0x00, 0x03, 'f',
1954 'o', 'o', 0x00, 0x03,
1955 'f', 'o', 'o', 0x00,
1956 0x03, 'b', 'a', 'r'
1958 const unsigned char kV3FrameData[] = {
1959 0x80, spdy_version_ch_, 0x00, 0x01,
1960 0x00, 0x00, 0x00, 0x2a,
1961 0x00, 0x00, 0x00, 0x01,
1962 0x00, 0x00, 0x00, 0x00,
1963 kPri, 0x00, 0x00, 0x00,
1964 0x00, 0x02, 0x00, 0x00,
1965 0x00, 0x03, 'b', 'a',
1966 'r', 0x00, 0x00, 0x00,
1967 0x03, 'f', 'o', 'o',
1968 0x00, 0x00, 0x00, 0x03,
1969 'f', 'o', 'o', 0x00,
1970 0x00, 0x00, 0x03, 'b',
1971 'a', 'r'
1973 SpdySynStreamIR syn_stream(1);
1974 syn_stream.set_priority(framer.GetLowestPriority());
1975 syn_stream.SetHeader("bar", "foo");
1976 syn_stream.SetHeader("foo", "bar");
1977 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1978 if (IsSpdy2()) {
1979 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1980 } else if (IsSpdy3()) {
1981 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1982 } else {
1983 LOG(FATAL) << "Unsupported version in test.";
1988 const char kDescription[] =
1989 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1990 "max stream ID";
1992 const unsigned char kV2FrameData[] = {
1993 0x80, spdy_version_ch_, 0x00, 0x01,
1994 0x01, 0x00, 0x00, 0x1D,
1995 0x7f, 0xff, 0xff, 0xff,
1996 0x7f, 0xff, 0xff, 0xff,
1997 0x00, 0x00, 0x00, 0x02,
1998 0x00, 0x00, 0x00, 0x03,
1999 'f', 'o', 'o', 0x00,
2000 0x03, 'f', 'o', 'o',
2001 0x00, 0x03, 'b', 'a',
2004 const unsigned char kV3FrameData[] = {
2005 0x80, spdy_version_ch_, 0x00, 0x01,
2006 0x01, 0x00, 0x00, 0x27,
2007 0x7f, 0xff, 0xff, 0xff,
2008 0x7f, 0xff, 0xff, 0xff,
2009 0x00, 0x00, 0x00, 0x00,
2010 0x00, 0x02, 0x00, 0x00,
2011 0x00, 0x00, 0x00, 0x00,
2012 0x00, 0x03, 'f', 'o',
2013 'o', 0x00, 0x00, 0x00,
2014 0x03, 'f', 'o', 'o',
2015 0x00, 0x00, 0x00, 0x03,
2016 'b', 'a', 'r'
2018 SpdySynStreamIR syn_stream(0x7fffffff);
2019 syn_stream.set_associated_to_stream_id(0x7fffffff);
2020 syn_stream.set_priority(framer.GetHighestPriority());
2021 syn_stream.set_fin(true);
2022 syn_stream.SetHeader("", "foo");
2023 syn_stream.SetHeader("foo", "bar");
2024 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2025 if (IsSpdy2()) {
2026 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2027 } else if (IsSpdy3()) {
2028 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2029 } else {
2030 LOG(FATAL) << "Unsupported version in test.";
2035 const char kDescription[] =
2036 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
2037 "max stream ID";
2039 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
2040 const unsigned char kV2FrameData[] = {
2041 0x80, spdy_version_ch_, 0x00, 0x01,
2042 0x01, 0x00, 0x00, 0x1D,
2043 0x7f, 0xff, 0xff, 0xff,
2044 0x7f, 0xff, 0xff, 0xff,
2045 kPri, 0x00, 0x00, 0x02,
2046 0x00, 0x03, 'b', 'a',
2047 'r', 0x00, 0x03, 'f',
2048 'o', 'o', 0x00, 0x03,
2049 'f', 'o', 'o', 0x00,
2050 0x00
2052 const unsigned char kV3FrameData[] = {
2053 0x80, spdy_version_ch_, 0x00, 0x01,
2054 0x01, 0x00, 0x00, 0x27,
2055 0x7f, 0xff, 0xff, 0xff,
2056 0x7f, 0xff, 0xff, 0xff,
2057 kPri, 0x00, 0x00, 0x00,
2058 0x00, 0x02, 0x00, 0x00,
2059 0x00, 0x03, 'b', 'a',
2060 'r', 0x00, 0x00, 0x00,
2061 0x03, 'f', 'o', 'o',
2062 0x00, 0x00, 0x00, 0x03,
2063 'f', 'o', 'o', 0x00,
2064 0x00, 0x00, 0x00
2066 SpdySynStreamIR syn_stream(0x7fffffff);
2067 syn_stream.set_associated_to_stream_id(0x7fffffff);
2068 syn_stream.set_priority(1);
2069 syn_stream.set_fin(true);
2070 syn_stream.SetHeader("bar", "foo");
2071 syn_stream.SetHeader("foo", "");
2072 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2073 if (IsSpdy2()) {
2074 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2075 } else if (IsSpdy3()) {
2076 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2077 } else {
2078 LOG(FATAL) << "Unsupported version in test.";
2083 // TODO(phajdan.jr): Clean up after we no longer need
2084 // to workaround http://crbug.com/139744.
2085 #if !defined(USE_SYSTEM_ZLIB)
2086 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2087 if (!IsSpdy2() && !IsSpdy3()) {
2088 // SYN_STREAM not supported for SPDY>3
2089 return;
2091 SpdyFramer framer(spdy_version_);
2092 framer.set_enable_compression(true);
2095 const char kDescription[] =
2096 "SYN_STREAM frame, low pri, no FIN";
2097 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2099 const unsigned char kV2FrameData[] = {
2100 0x80, spdy_version_ch_, 0x00, 0x01,
2101 0x00, 0x00, 0x00, 0x36,
2102 0x00, 0x00, 0x00, 0x01,
2103 0x00, 0x00, 0x00, 0x00,
2104 0x80, 0x00, 0x38, 0xea,
2105 0xdf, 0xa2, 0x51, 0xb2,
2106 0x62, 0x60, 0x62, 0x60,
2107 0x4e, 0x4a, 0x2c, 0x62,
2108 0x60, 0x06, 0x08, 0xa0,
2109 0xb4, 0xfc, 0x7c, 0x80,
2110 0x00, 0x62, 0x60, 0x4e,
2111 0xcb, 0xcf, 0x67, 0x60,
2112 0x06, 0x08, 0xa0, 0xa4,
2113 0xc4, 0x22, 0x80, 0x00,
2114 0x02, 0x00, 0x00, 0x00,
2115 0xff, 0xff,
2117 const unsigned char kV3FrameData[] = {
2118 0x80, spdy_version_ch_, 0x00, 0x01,
2119 0x00, 0x00, 0x00, 0x37,
2120 0x00, 0x00, 0x00, 0x01,
2121 0x00, 0x00, 0x00, 0x00,
2122 0x80, 0x00, 0x38, 0xEA,
2123 0xE3, 0xC6, 0xA7, 0xC2,
2124 0x02, 0xE5, 0x0E, 0x50,
2125 0xC2, 0x4B, 0x4A, 0x04,
2126 0xE5, 0x0B, 0x66, 0x80,
2127 0x00, 0x4A, 0xCB, 0xCF,
2128 0x07, 0x08, 0x20, 0x10,
2129 0x95, 0x96, 0x9F, 0x0F,
2130 0xA2, 0x00, 0x02, 0x28,
2131 0x29, 0xB1, 0x08, 0x20,
2132 0x80, 0x00, 0x00, 0x00,
2133 0x00, 0xFF, 0xFF,
2135 const unsigned char kV2SIMDFrameData[] = {
2136 0x80, spdy_version_ch_, 0x00, 0x01,
2137 0x00, 0x00, 0x00, 0x33,
2138 0x00, 0x00, 0x00, 0x01,
2139 0x00, 0x00, 0x00, 0x00,
2140 0x80, 0x00, 0x38, 0xea,
2141 0xdf, 0xa2, 0x51, 0xb2,
2142 0x62, 0x60, 0x62, 0x60,
2143 0x4e, 0x4a, 0x2c, 0x62,
2144 0x60, 0x06, 0x08, 0xa0,
2145 0xb4, 0xfc, 0x7c, 0x80,
2146 0x00, 0x62, 0x60, 0x06,
2147 0x13, 0x00, 0x01, 0x94,
2148 0x94, 0x58, 0x04, 0x10,
2149 0x40, 0x00, 0x00, 0x00,
2150 0x00, 0xff, 0xff,
2152 const unsigned char kV3SIMDFrameData[] = {
2153 0x80, spdy_version_ch_, 0x00, 0x01,
2154 0x00, 0x00, 0x00, 0x32,
2155 0x00, 0x00, 0x00, 0x01,
2156 0x00, 0x00, 0x00, 0x00,
2157 0x80, 0x00, 0x38, 0xea,
2158 0xe3, 0xc6, 0xa7, 0xc2,
2159 0x02, 0xe5, 0x0e, 0x50,
2160 0xc2, 0x4b, 0x4a, 0x04,
2161 0xe5, 0x0b, 0x66, 0x80,
2162 0x00, 0x4a, 0xcb, 0xcf,
2163 0x07, 0x08, 0x20, 0x24,
2164 0x0a, 0x20, 0x80, 0x92,
2165 0x12, 0x8b, 0x00, 0x02,
2166 0x08, 0x00, 0x00, 0x00,
2167 0xff, 0xff,
2170 SpdySynStreamIR syn_stream(1);
2171 syn_stream.set_priority(priority);
2172 syn_stream.SetHeader("bar", "foo");
2173 syn_stream.SetHeader("foo", "bar");
2174 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2175 const unsigned char* frame_data =
2176 reinterpret_cast<const unsigned char*>(frame->data());
2177 if (IsSpdy2()) {
2178 // Try comparing with SIMD version, if that fails, do a failing check
2179 // with pretty printing against non-SIMD version
2180 if (memcmp(frame_data,
2181 kV2SIMDFrameData,
2182 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2183 CompareCharArraysWithHexError(kDescription,
2184 frame_data,
2185 frame->size(),
2186 kV2FrameData,
2187 arraysize(kV2FrameData));
2189 } else if (IsSpdy3()) {
2190 if (memcmp(frame_data,
2191 kV3SIMDFrameData,
2192 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2193 CompareCharArraysWithHexError(kDescription,
2194 frame_data,
2195 frame->size(),
2196 kV3FrameData,
2197 arraysize(kV3FrameData));
2199 } else {
2200 LOG(FATAL) << "Unsupported version in test.";
2204 #endif // !defined(USE_SYSTEM_ZLIB)
2206 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2207 if (spdy_version_ > SPDY3) {
2208 // SYN_REPLY unsupported in SPDY>3
2209 return;
2211 SpdyFramer framer(spdy_version_);
2212 framer.set_enable_compression(false);
2215 const char kDescription[] = "SYN_REPLY frame, no FIN";
2217 const unsigned char kV2FrameData[] = {
2218 0x80, spdy_version_ch_, 0x00, 0x02,
2219 0x00, 0x00, 0x00, 0x1C,
2220 0x00, 0x00, 0x00, 0x01,
2221 0x00, 0x00, 0x00, 0x02,
2222 0x00, 0x03, 'b', 'a',
2223 'r', 0x00, 0x03, 'f',
2224 'o', 'o', 0x00, 0x03,
2225 'f', 'o', 'o', 0x00,
2226 0x03, 'b', 'a', 'r'
2228 const unsigned char kV3FrameData[] = {
2229 0x80, spdy_version_ch_, 0x00, 0x02,
2230 0x00, 0x00, 0x00, 0x24,
2231 0x00, 0x00, 0x00, 0x01,
2232 0x00, 0x00, 0x00, 0x02,
2233 0x00, 0x00, 0x00, 0x03,
2234 'b', 'a', 'r', 0x00,
2235 0x00, 0x00, 0x03, 'f',
2236 'o', 'o', 0x00, 0x00,
2237 0x00, 0x03, 'f', 'o',
2238 'o', 0x00, 0x00, 0x00,
2239 0x03, 'b', 'a', 'r'
2241 SpdySynReplyIR syn_reply(1);
2242 syn_reply.SetHeader("bar", "foo");
2243 syn_reply.SetHeader("foo", "bar");
2244 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2245 if (IsSpdy2()) {
2246 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2247 } else if (IsSpdy3()) {
2248 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2249 } else {
2250 LOG(FATAL) << "Unsupported version in test.";
2255 const char kDescription[] =
2256 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2258 const unsigned char kV2FrameData[] = {
2259 0x80, spdy_version_ch_, 0x00, 0x02,
2260 0x01, 0x00, 0x00, 0x19,
2261 0x7f, 0xff, 0xff, 0xff,
2262 0x00, 0x00, 0x00, 0x02,
2263 0x00, 0x00, 0x00, 0x03,
2264 'f', 'o', 'o', 0x00,
2265 0x03, 'f', 'o', 'o',
2266 0x00, 0x03, 'b', 'a',
2269 const unsigned char kV3FrameData[] = {
2270 0x80, spdy_version_ch_, 0x00, 0x02,
2271 0x01, 0x00, 0x00, 0x21,
2272 0x7f, 0xff, 0xff, 0xff,
2273 0x00, 0x00, 0x00, 0x02,
2274 0x00, 0x00, 0x00, 0x00,
2275 0x00, 0x00, 0x00, 0x03,
2276 'f', 'o', 'o', 0x00,
2277 0x00, 0x00, 0x03, 'f',
2278 'o', 'o', 0x00, 0x00,
2279 0x00, 0x03, 'b', 'a',
2282 SpdySynReplyIR syn_reply(0x7fffffff);
2283 syn_reply.set_fin(true);
2284 syn_reply.SetHeader("", "foo");
2285 syn_reply.SetHeader("foo", "bar");
2286 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2287 if (IsSpdy2()) {
2288 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2289 } else if (IsSpdy3()) {
2290 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2291 } else {
2292 LOG(FATAL) << "Unsupported version in test.";
2297 const char kDescription[] =
2298 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2300 const unsigned char kV2FrameData[] = {
2301 0x80, spdy_version_ch_, 0x00, 0x02,
2302 0x01, 0x00, 0x00, 0x19,
2303 0x7f, 0xff, 0xff, 0xff,
2304 0x00, 0x00, 0x00, 0x02,
2305 0x00, 0x03, 'b', 'a',
2306 'r', 0x00, 0x03, 'f',
2307 'o', 'o', 0x00, 0x03,
2308 'f', 'o', 'o', 0x00,
2309 0x00
2311 const unsigned char kV3FrameData[] = {
2312 0x80, spdy_version_ch_, 0x00, 0x02,
2313 0x01, 0x00, 0x00, 0x21,
2314 0x7f, 0xff, 0xff, 0xff,
2315 0x00, 0x00, 0x00, 0x02,
2316 0x00, 0x00, 0x00, 0x03,
2317 'b', 'a', 'r', 0x00,
2318 0x00, 0x00, 0x03, 'f',
2319 'o', 'o', 0x00, 0x00,
2320 0x00, 0x03, 'f', 'o',
2321 'o', 0x00, 0x00, 0x00,
2322 0x00
2324 SpdySynReplyIR syn_reply(0x7fffffff);
2325 syn_reply.set_fin(true);
2326 syn_reply.SetHeader("bar", "foo");
2327 syn_reply.SetHeader("foo", "");
2328 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2329 if (IsSpdy2()) {
2330 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2331 } else if (IsSpdy3()) {
2332 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2333 } else {
2334 LOG(FATAL) << "Unsupported version in test.";
2339 // TODO(phajdan.jr): Clean up after we no longer need
2340 // to workaround http://crbug.com/139744.
2341 #if !defined(USE_SYSTEM_ZLIB)
2342 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2343 if (spdy_version_ > SPDY3) {
2344 // SYN_REPLY unsupported in SPDY>3
2345 return;
2347 SpdyFramer framer(spdy_version_);
2348 framer.set_enable_compression(true);
2351 const char kDescription[] = "SYN_REPLY frame, no FIN";
2353 const unsigned char kV2FrameData[] = {
2354 0x80, spdy_version_ch_, 0x00, 0x02,
2355 0x00, 0x00, 0x00, 0x32,
2356 0x00, 0x00, 0x00, 0x01,
2357 0x00, 0x00, 0x38, 0xea,
2358 0xdf, 0xa2, 0x51, 0xb2,
2359 0x62, 0x60, 0x62, 0x60,
2360 0x4e, 0x4a, 0x2c, 0x62,
2361 0x60, 0x06, 0x08, 0xa0,
2362 0xb4, 0xfc, 0x7c, 0x80,
2363 0x00, 0x62, 0x60, 0x4e,
2364 0xcb, 0xcf, 0x67, 0x60,
2365 0x06, 0x08, 0xa0, 0xa4,
2366 0xc4, 0x22, 0x80, 0x00,
2367 0x02, 0x00, 0x00, 0x00,
2368 0xff, 0xff,
2370 const unsigned char kV3FrameData[] = {
2371 0x80, spdy_version_ch_, 0x00, 0x02,
2372 0x00, 0x00, 0x00, 0x31,
2373 0x00, 0x00, 0x00, 0x01,
2374 0x38, 0xea, 0xe3, 0xc6,
2375 0xa7, 0xc2, 0x02, 0xe5,
2376 0x0e, 0x50, 0xc2, 0x4b,
2377 0x4a, 0x04, 0xe5, 0x0b,
2378 0x66, 0x80, 0x00, 0x4a,
2379 0xcb, 0xcf, 0x07, 0x08,
2380 0x20, 0x10, 0x95, 0x96,
2381 0x9f, 0x0f, 0xa2, 0x00,
2382 0x02, 0x28, 0x29, 0xb1,
2383 0x08, 0x20, 0x80, 0x00,
2384 0x00, 0x00, 0x00, 0xff,
2385 0xff,
2387 const unsigned char kV2SIMDFrameData[] = {
2388 0x80, spdy_version_ch_, 0x00, 0x02,
2389 0x00, 0x00, 0x00, 0x2f,
2390 0x00, 0x00, 0x00, 0x01,
2391 0x00, 0x00, 0x38, 0xea,
2392 0xdf, 0xa2, 0x51, 0xb2,
2393 0x62, 0x60, 0x62, 0x60,
2394 0x4e, 0x4a, 0x2c, 0x62,
2395 0x60, 0x06, 0x08, 0xa0,
2396 0xb4, 0xfc, 0x7c, 0x80,
2397 0x00, 0x62, 0x60, 0x06,
2398 0x13, 0x00, 0x01, 0x94,
2399 0x94, 0x58, 0x04, 0x10,
2400 0x40, 0x00, 0x00, 0x00,
2401 0x00, 0xff, 0xff,
2403 const unsigned char kV3SIMDFrameData[] = {
2404 0x80, spdy_version_ch_, 0x00, 0x02,
2405 0x00, 0x00, 0x00, 0x2c,
2406 0x00, 0x00, 0x00, 0x01,
2407 0x38, 0xea, 0xe3, 0xc6,
2408 0xa7, 0xc2, 0x02, 0xe5,
2409 0x0e, 0x50, 0xc2, 0x4b,
2410 0x4a, 0x04, 0xe5, 0x0b,
2411 0x66, 0x80, 0x00, 0x4a,
2412 0xcb, 0xcf, 0x07, 0x08,
2413 0x20, 0x24, 0x0a, 0x20,
2414 0x80, 0x92, 0x12, 0x8b,
2415 0x00, 0x02, 0x08, 0x00,
2416 0x00, 0x00, 0xff, 0xff,
2419 SpdySynReplyIR syn_reply(1);
2420 syn_reply.SetHeader("bar", "foo");
2421 syn_reply.SetHeader("foo", "bar");
2422 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2423 const unsigned char* frame_data =
2424 reinterpret_cast<const unsigned char*>(frame->data());
2425 if (IsSpdy2()) {
2426 // Try comparing with SIMD version, if that fails, do a failing check
2427 // with pretty printing against non-SIMD version
2428 if (memcmp(frame_data,
2429 kV2SIMDFrameData,
2430 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2431 CompareCharArraysWithHexError(kDescription,
2432 frame_data,
2433 frame->size(),
2434 kV2FrameData,
2435 arraysize(kV2FrameData));
2437 } else if (IsSpdy3()) {
2438 if (memcmp(frame_data,
2439 kV3SIMDFrameData,
2440 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2441 CompareCharArraysWithHexError(kDescription,
2442 frame_data,
2443 frame->size(),
2444 kV3FrameData,
2445 arraysize(kV3FrameData));
2447 } else {
2448 LOG(FATAL) << "Unsupported version in test.";
2452 #endif // !defined(USE_SYSTEM_ZLIB)
2454 TEST_P(SpdyFramerTest, CreateRstStream) {
2455 SpdyFramer framer(spdy_version_);
2458 const char kDescription[] = "RST_STREAM frame";
2459 const unsigned char kV3FrameData[] = { // Also applies for V2.
2460 0x80, spdy_version_ch_, 0x00, 0x03,
2461 0x00, 0x00, 0x00, 0x08,
2462 0x00, 0x00, 0x00, 0x01,
2463 0x00, 0x00, 0x00, 0x01,
2465 const unsigned char kH2FrameData[] = {
2466 0x00, 0x00, 0x07, 0x03,
2467 0x00, 0x00, 0x00, 0x00,
2468 0x01, 0x00, 0x00, 0x00,
2469 0x01, 0x52, 0x53, 0x54
2471 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2472 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2473 if (IsHttp2()) {
2474 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2475 } else {
2476 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2481 const char kDescription[] = "RST_STREAM frame with max stream ID";
2482 const unsigned char kV3FrameData[] = { // Also applies for V2.
2483 0x80, spdy_version_ch_, 0x00, 0x03,
2484 0x00, 0x00, 0x00, 0x08,
2485 0x7f, 0xff, 0xff, 0xff,
2486 0x00, 0x00, 0x00, 0x01,
2488 const unsigned char kH2FrameData[] = {
2489 0x00, 0x00, 0x04, 0x03,
2490 0x00, 0x7f, 0xff, 0xff,
2491 0xff, 0x00, 0x00, 0x00,
2492 0x01,
2494 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2495 RST_STREAM_PROTOCOL_ERROR,
2496 "");
2497 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2498 if (IsHttp2()) {
2499 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2500 } else {
2501 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2506 const char kDescription[] = "RST_STREAM frame with max status code";
2507 const unsigned char kV3FrameData[] = { // Also applies for V2.
2508 0x80, spdy_version_ch_, 0x00, 0x03,
2509 0x00, 0x00, 0x00, 0x08,
2510 0x7f, 0xff, 0xff, 0xff,
2511 0x00, 0x00, 0x00, 0x06,
2513 const unsigned char kH2FrameData[] = {
2514 0x00, 0x00, 0x04, 0x03,
2515 0x00, 0x7f, 0xff, 0xff,
2516 0xff, 0x00, 0x00, 0x00,
2517 0x02,
2519 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2520 RST_STREAM_INTERNAL_ERROR,
2521 "");
2522 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2523 if (IsHttp2()) {
2524 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2525 } else {
2526 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2531 TEST_P(SpdyFramerTest, CreateSettings) {
2532 SpdyFramer framer(spdy_version_);
2535 const char kDescription[] = "Network byte order SETTINGS frame";
2537 const unsigned char kV2FrameData[] = {
2538 0x80, spdy_version_ch_, 0x00, 0x04,
2539 0x00, 0x00, 0x00, 0x0c,
2540 0x00, 0x00, 0x00, 0x01,
2541 0x07, 0x00, 0x00, 0x01,
2542 0x0a, 0x0b, 0x0c, 0x0d,
2544 const unsigned char kV3FrameData[] = {
2545 0x80, spdy_version_ch_, 0x00, 0x04,
2546 0x00, 0x00, 0x00, 0x0c,
2547 0x00, 0x00, 0x00, 0x01,
2548 0x01, 0x00, 0x00, 0x07,
2549 0x0a, 0x0b, 0x0c, 0x0d,
2551 const unsigned char kH2FrameData[] = {
2552 0x00, 0x00, 0x06, 0x04,
2553 0x00, 0x00, 0x00, 0x00,
2554 0x00, 0x00, 0x04, 0x0a,
2555 0x0b, 0x0c, 0x0d,
2558 uint32 kValue = 0x0a0b0c0d;
2559 SpdySettingsIR settings_ir;
2561 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2562 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2563 settings_ir.AddSetting(kId,
2564 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2565 kFlags & SETTINGS_FLAG_PERSISTED,
2566 kValue);
2568 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2569 if (IsSpdy2()) {
2570 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2571 } else if (IsSpdy3()) {
2572 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2573 } else {
2574 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2579 const char kDescription[] = "Basic SETTINGS frame";
2581 const unsigned char kV2FrameData[] = {
2582 0x80, spdy_version_ch_, 0x00, 0x04,
2583 0x00, 0x00, 0x00, 0x24,
2584 0x00, 0x00, 0x00, 0x04,
2585 0x01, 0x00, 0x00, 0x00, // 1st Setting
2586 0x00, 0x00, 0x00, 0x05,
2587 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2588 0x00, 0x00, 0x00, 0x06,
2589 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2590 0x00, 0x00, 0x00, 0x07,
2591 0x04, 0x00, 0x00, 0x00, // 4th Setting
2592 0x00, 0x00, 0x00, 0x08,
2594 const unsigned char kV3FrameData[] = {
2595 0x80, spdy_version_ch_, 0x00, 0x04,
2596 0x00, 0x00, 0x00, 0x24,
2597 0x00, 0x00, 0x00, 0x04,
2598 0x00, 0x00, 0x00, 0x01, // 1st Setting
2599 0x00, 0x00, 0x00, 0x05,
2600 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2601 0x00, 0x00, 0x00, 0x06,
2602 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2603 0x00, 0x00, 0x00, 0x07,
2604 0x00, 0x00, 0x00, 0x04, // 4th Setting
2605 0x00, 0x00, 0x00, 0x08,
2607 // These end up seemingly out of order because of the way that our internal
2608 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2609 // the wire.
2610 const unsigned char kH2FrameData[] = {
2611 0x00, 0x00, 0x18, 0x04,
2612 0x00, 0x00, 0x00, 0x00,
2613 0x00, 0x00, 0x03, // 3rd Setting
2614 0x00, 0x00, 0x00, 0x07,
2615 0x00, 0x04, // 4th Setting
2616 0x00, 0x00, 0x00, 0x08,
2617 0x00, 0x01, // 1st Setting
2618 0x00, 0x00, 0x00, 0x05,
2619 0x00, 0x02, // 2nd Setting
2620 0x00, 0x00, 0x00, 0x06,
2623 SpdySettingsIR settings_ir;
2624 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2625 false, // persist
2626 false, // persisted
2628 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2629 false, // persist
2630 false, // persisted
2632 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2633 false, // persist
2634 false, // persisted
2636 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2637 false, // persist
2638 false, // persisted
2640 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2642 if (IsSpdy2()) {
2643 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2644 } else if (IsSpdy3()) {
2645 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2646 } else {
2647 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2652 const char kDescription[] = "Empty SETTINGS frame";
2654 const unsigned char kV3FrameData[] = { // Also applies for V2.
2655 0x80, spdy_version_ch_, 0x00, 0x04,
2656 0x00, 0x00, 0x00, 0x04,
2657 0x00, 0x00, 0x00, 0x00,
2659 const unsigned char kH2FrameData[] = {
2660 0x00, 0x00, 0x00, 0x04,
2661 0x00, 0x00, 0x00, 0x00,
2662 0x00,
2664 SpdySettingsIR settings_ir;
2665 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2666 if (IsHttp2()) {
2667 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2668 } else {
2669 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2674 TEST_P(SpdyFramerTest, CreatePingFrame) {
2675 SpdyFramer framer(spdy_version_);
2678 const char kDescription[] = "PING frame";
2679 const unsigned char kV3FrameData[] = { // Also applies for V2.
2680 0x80, spdy_version_ch_, 0x00, 0x06,
2681 0x00, 0x00, 0x00, 0x04,
2682 0x12, 0x34, 0x56, 0x78,
2684 const unsigned char kH2FrameData[] = {
2685 0x00, 0x00, 0x08, 0x06,
2686 0x00, 0x00, 0x00, 0x00,
2687 0x00, 0x12, 0x34, 0x56,
2688 0x78, 0x9a, 0xbc, 0xde,
2689 0xff,
2691 const unsigned char kH2FrameDataWithAck[] = {
2692 0x00, 0x00, 0x08, 0x06,
2693 0x01, 0x00, 0x00, 0x00,
2694 0x00, 0x12, 0x34, 0x56,
2695 0x78, 0x9a, 0xbc, 0xde,
2696 0xff,
2698 scoped_ptr<SpdyFrame> frame;
2699 if (IsHttp2()) {
2700 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2701 SpdyPingIR ping_ir(kPingId);
2702 // Tests SpdyPingIR when the ping is not an ack.
2703 ASSERT_FALSE(ping_ir.is_ack());
2704 frame.reset(framer.SerializePing(ping_ir));
2705 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2707 // Tests SpdyPingIR when the ping is an ack.
2708 ping_ir.set_is_ack(true);
2709 frame.reset(framer.SerializePing(ping_ir));
2710 CompareFrame(kDescription, *frame, kH2FrameDataWithAck,
2711 arraysize(kH2FrameDataWithAck));
2713 } else {
2714 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2715 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2720 TEST_P(SpdyFramerTest, CreateGoAway) {
2721 SpdyFramer framer(spdy_version_);
2724 const char kDescription[] = "GOAWAY frame";
2725 const unsigned char kV2FrameData[] = {
2726 0x80, spdy_version_ch_, 0x00, 0x07,
2727 0x00, 0x00, 0x00, 0x04,
2728 0x00, 0x00, 0x00, 0x00, // Stream Id
2730 const unsigned char kV3FrameData[] = {
2731 0x80, spdy_version_ch_, 0x00, 0x07,
2732 0x00, 0x00, 0x00, 0x08,
2733 0x00, 0x00, 0x00, 0x00, // Stream Id
2734 0x00, 0x00, 0x00, 0x00, // Status
2736 const unsigned char kH2FrameData[] = {
2737 0x00, 0x00, 0x0a, 0x07,
2738 0x00, 0x00, 0x00, 0x00,
2739 0x00, 0x00, 0x00, 0x00, // Stream id
2740 0x00, 0x00, 0x00, 0x00, // Status
2741 0x00, 0x47, 0x41, // Opaque Description
2743 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2744 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2745 if (IsSpdy2()) {
2746 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2747 } else if (IsSpdy3()) {
2748 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2749 } else {
2750 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2755 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2756 const unsigned char kV2FrameData[] = {
2757 0x80, spdy_version_ch_, 0x00, 0x07,
2758 0x00, 0x00, 0x00, 0x04,
2759 0x7f, 0xff, 0xff, 0xff, // Stream Id
2761 const unsigned char kV3FrameData[] = {
2762 0x80, spdy_version_ch_, 0x00, 0x07,
2763 0x00, 0x00, 0x00, 0x08,
2764 0x7f, 0xff, 0xff, 0xff, // Stream Id
2765 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2767 const unsigned char kH2FrameData[] = {
2768 0x00, 0x00, 0x0a, 0x07,
2769 0x00, 0x00, 0x00, 0x00,
2770 0x00, 0x7f, 0xff, 0xff, // Stream Id
2771 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2772 0x02, 0x47, 0x41, // Opaque Description
2774 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2775 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2776 if (IsSpdy2()) {
2777 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2778 } else if (IsSpdy3()) {
2779 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2780 } else {
2781 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2786 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2787 SpdyFramer framer(spdy_version_);
2788 framer.set_enable_compression(false);
2791 const char kDescription[] = "HEADERS frame, no FIN";
2793 const unsigned char kV2FrameData[] = {
2794 0x80, spdy_version_ch_, 0x00, 0x08,
2795 0x00, 0x00, 0x00, 0x1C,
2796 0x00, 0x00, 0x00, 0x01,
2797 0x00, 0x00, 0x00, 0x02,
2798 0x00, 0x03, 'b', 'a',
2799 'r', 0x00, 0x03, 'f',
2800 'o', 'o', 0x00, 0x03,
2801 'f', 'o', 'o', 0x00,
2802 0x03, 'b', 'a', 'r'
2804 const unsigned char kV3FrameData[] = {
2805 0x80, spdy_version_ch_, 0x00, 0x08,
2806 0x00, 0x00, 0x00, 0x24,
2807 0x00, 0x00, 0x00, 0x01,
2808 0x00, 0x00, 0x00, 0x02,
2809 0x00, 0x00, 0x00, 0x03,
2810 'b', 'a', 'r', 0x00,
2811 0x00, 0x00, 0x03, 'f',
2812 'o', 'o', 0x00, 0x00,
2813 0x00, 0x03, 'f', 'o',
2814 'o', 0x00, 0x00, 0x00,
2815 0x03, 'b', 'a', 'r'
2817 const unsigned char kH2FrameData[] = {
2818 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2819 0x04, 0x00, 0x00, 0x00, // Stream 1
2820 0x01, 0x00, 0x03, 0x62, // @.ba
2821 0x61, 0x72, 0x03, 0x66, // r.fo
2822 0x6f, 0x6f, 0x00, 0x03, // o@.f
2823 0x66, 0x6f, 0x6f, 0x03, // oo.b
2824 0x62, 0x61, 0x72, // ar
2826 SpdyHeadersIR headers_ir(1);
2827 headers_ir.SetHeader("bar", "foo");
2828 headers_ir.SetHeader("foo", "bar");
2829 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2830 if (IsSpdy2()) {
2831 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2832 } else if (IsSpdy3()) {
2833 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2834 } else {
2835 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2840 const char kDescription[] =
2841 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2843 const unsigned char kV2FrameData[] = {
2844 0x80, spdy_version_ch_, 0x00, 0x08,
2845 0x01, 0x00, 0x00, 0x19,
2846 0x7f, 0xff, 0xff, 0xff,
2847 0x00, 0x00, 0x00, 0x02,
2848 0x00, 0x00, 0x00, 0x03,
2849 'f', 'o', 'o', 0x00,
2850 0x03, 'f', 'o', 'o',
2851 0x00, 0x03, 'b', 'a',
2854 const unsigned char kV3FrameData[] = {
2855 0x80, spdy_version_ch_, 0x00, 0x08,
2856 0x01, 0x00, 0x00, 0x21,
2857 0x7f, 0xff, 0xff, 0xff,
2858 0x00, 0x00, 0x00, 0x02,
2859 0x00, 0x00, 0x00, 0x00,
2860 0x00, 0x00, 0x00, 0x03,
2861 'f', 'o', 'o', 0x00,
2862 0x00, 0x00, 0x03, 'f',
2863 'o', 'o', 0x00, 0x00,
2864 0x00, 0x03, 'b', 'a',
2867 const unsigned char kH2FrameData[] = {
2868 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2869 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2870 0xff, 0x00, 0x00, 0x03, // @..
2871 0x66, 0x6f, 0x6f, 0x00, // foo@
2872 0x03, 0x66, 0x6f, 0x6f, // .foo
2873 0x03, 0x62, 0x61, 0x72, // .bar
2875 SpdyHeadersIR headers_ir(0x7fffffff);
2876 headers_ir.set_fin(true);
2877 headers_ir.SetHeader("", "foo");
2878 headers_ir.SetHeader("foo", "bar");
2879 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2880 if (IsSpdy2()) {
2881 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2882 } else if (IsSpdy3()) {
2883 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2884 } else {
2885 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2890 const char kDescription[] =
2891 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2893 const unsigned char kV2FrameData[] = {
2894 0x80, spdy_version_ch_, 0x00, 0x08,
2895 0x01, 0x00, 0x00, 0x19,
2896 0x7f, 0xff, 0xff, 0xff,
2897 0x00, 0x00, 0x00, 0x02,
2898 0x00, 0x03, 'b', 'a',
2899 'r', 0x00, 0x03, 'f',
2900 'o', 'o', 0x00, 0x03,
2901 'f', 'o', 'o', 0x00,
2902 0x00
2904 const unsigned char kV3FrameData[] = {
2905 0x80, spdy_version_ch_, 0x00, 0x08,
2906 0x01, 0x00, 0x00, 0x21,
2907 0x7f, 0xff, 0xff, 0xff,
2908 0x00, 0x00, 0x00, 0x02,
2909 0x00, 0x00, 0x00, 0x03,
2910 'b', 'a', 'r', 0x00,
2911 0x00, 0x00, 0x03, 'f',
2912 'o', 'o', 0x00, 0x00,
2913 0x00, 0x03, 'f', 'o',
2914 'o', 0x00, 0x00, 0x00,
2915 0x00
2917 const unsigned char kH2FrameData[] = {
2918 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2919 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2920 0xff, 0x00, 0x03, 0x62, // @.b
2921 0x61, 0x72, 0x03, 0x66, // ar.f
2922 0x6f, 0x6f, 0x00, 0x03, // oo@.
2923 0x66, 0x6f, 0x6f, 0x00, // foo.
2925 SpdyHeadersIR headers_ir(0x7fffffff);
2926 headers_ir.set_fin(true);
2927 headers_ir.SetHeader("bar", "foo");
2928 headers_ir.SetHeader("foo", "");
2929 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2930 if (IsSpdy2()) {
2931 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2932 } else if (IsSpdy3()) {
2933 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2934 } else {
2935 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2940 const char kDescription[] =
2941 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2943 const unsigned char kH2FrameData[] = {
2944 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2945 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2946 0xff, 0x00, 0x00, 0x00, // exclusive, parent stream
2947 0x00, 0xdb, // weight
2948 0x00, 0x03, 0x62, 0x61, // @.ba
2949 0x72, 0x03, 0x66, 0x6f, // r.fo
2950 0x6f, 0x00, 0x03, 0x66, // o@.f
2951 0x6f, 0x6f, 0x00, // oo.
2953 SpdyHeadersIR headers_ir(0x7fffffff);
2954 headers_ir.set_fin(true);
2955 headers_ir.set_priority(1);
2956 headers_ir.set_has_priority(true);
2957 headers_ir.SetHeader("bar", "foo");
2958 headers_ir.SetHeader("foo", "");
2959 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2960 if (IsSpdy2() || IsSpdy3()) {
2961 // HEADERS with priority not supported.
2962 } else {
2963 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2968 const char kDescription[] =
2969 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2970 "exclusive=true, parent_stream=0";
2972 const unsigned char kH2FrameData[] = {
2973 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2974 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2975 0xff, 0x80, 0x00, 0x00, // exclusive, parent stream
2976 0x00, 0xdb, // weight
2977 0x00, 0x03, 0x62, 0x61, // @.ba
2978 0x72, 0x03, 0x66, 0x6f, // r.fo
2979 0x6f, 0x00, 0x03, 0x66, // o@.f
2980 0x6f, 0x6f, 0x00, // oo.
2982 SpdyHeadersIR headers_ir(0x7fffffff);
2983 headers_ir.set_fin(true);
2984 headers_ir.set_priority(1);
2985 headers_ir.set_has_priority(true);
2986 headers_ir.set_exclusive(true);
2987 headers_ir.set_parent_stream_id(0);
2988 headers_ir.SetHeader("bar", "foo");
2989 headers_ir.SetHeader("foo", "");
2990 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2991 if (IsSpdy2() || IsSpdy3()) {
2992 // HEADERS with priority not supported.
2993 } else {
2994 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
2999 const char kDescription[] =
3000 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
3001 "exclusive=false, parent_stream=max stream ID";
3003 const unsigned char kH2FrameData[] = {
3004 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
3005 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
3006 0xff, 0x7f, 0xff, 0xff, // exclusive, parent stream
3007 0xff, 0xdb, // weight
3008 0x00, 0x03, 0x62, 0x61, // @.ba
3009 0x72, 0x03, 0x66, 0x6f, // r.fo
3010 0x6f, 0x00, 0x03, 0x66, // o@.f
3011 0x6f, 0x6f, 0x00, // oo.
3013 SpdyHeadersIR headers_ir(0x7fffffff);
3014 headers_ir.set_fin(true);
3015 headers_ir.set_priority(1);
3016 headers_ir.set_has_priority(true);
3017 headers_ir.set_exclusive(false);
3018 headers_ir.set_parent_stream_id(0x7fffffff);
3019 headers_ir.SetHeader("bar", "foo");
3020 headers_ir.SetHeader("foo", "");
3021 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3022 if (IsSpdy2() || IsSpdy3()) {
3023 // HEADERS with priority not supported.
3024 } else {
3025 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3030 const char kDescription[] =
3031 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
3033 const unsigned char kH2FrameData[] = {
3034 0x00, 0x00, 0x15, 0x01, // Headers
3035 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
3036 // 0x7fffffff
3037 0xff, 0x05, 0x00, 0x00, // Pad length field
3038 0x03, 0x66, 0x6f, 0x6f, // .foo
3039 0x00, 0x03, 0x66, 0x6f, // @.fo
3040 0x6f, 0x03, 0x62, 0x61, // o.ba
3041 0x72, // r
3042 // Padding payload
3043 0x00, 0x00, 0x00, 0x00, 0x00,
3045 SpdyHeadersIR headers_ir(0x7fffffff);
3046 headers_ir.set_fin(true);
3047 headers_ir.SetHeader("", "foo");
3048 headers_ir.SetHeader("foo", "bar");
3049 headers_ir.set_padding_len(6);
3050 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3051 if (IsSpdy2() || IsSpdy3()) {
3052 // Padding is not supported.
3053 } else {
3054 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3059 // TODO(phajdan.jr): Clean up after we no longer need
3060 // to workaround http://crbug.com/139744.
3061 #if !defined(USE_SYSTEM_ZLIB)
3062 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
3063 SpdyFramer framer(spdy_version_);
3064 framer.set_enable_compression(true);
3067 const char kDescription[] = "HEADERS frame, no FIN";
3069 const unsigned char kV2FrameData[] = {
3070 0x80, spdy_version_ch_, 0x00, 0x08,
3071 0x00, 0x00, 0x00, 0x32,
3072 0x00, 0x00, 0x00, 0x01,
3073 0x00, 0x00, 0x38, 0xea,
3074 0xdf, 0xa2, 0x51, 0xb2,
3075 0x62, 0x60, 0x62, 0x60,
3076 0x4e, 0x4a, 0x2c, 0x62,
3077 0x60, 0x06, 0x08, 0xa0,
3078 0xb4, 0xfc, 0x7c, 0x80,
3079 0x00, 0x62, 0x60, 0x4e,
3080 0xcb, 0xcf, 0x67, 0x60,
3081 0x06, 0x08, 0xa0, 0xa4,
3082 0xc4, 0x22, 0x80, 0x00,
3083 0x02, 0x00, 0x00, 0x00,
3084 0xff, 0xff,
3086 const unsigned char kV3FrameData[] = {
3087 0x80, spdy_version_ch_, 0x00, 0x08,
3088 0x00, 0x00, 0x00, 0x31,
3089 0x00, 0x00, 0x00, 0x01,
3090 0x38, 0xea, 0xe3, 0xc6,
3091 0xa7, 0xc2, 0x02, 0xe5,
3092 0x0e, 0x50, 0xc2, 0x4b,
3093 0x4a, 0x04, 0xe5, 0x0b,
3094 0x66, 0x80, 0x00, 0x4a,
3095 0xcb, 0xcf, 0x07, 0x08,
3096 0x20, 0x10, 0x95, 0x96,
3097 0x9f, 0x0f, 0xa2, 0x00,
3098 0x02, 0x28, 0x29, 0xb1,
3099 0x08, 0x20, 0x80, 0x00,
3100 0x00, 0x00, 0x00, 0xff,
3101 0xff,
3103 const unsigned char kV2SIMDFrameData[] = {
3104 0x80, spdy_version_ch_, 0x00, 0x08,
3105 0x00, 0x00, 0x00, 0x2f,
3106 0x00, 0x00, 0x00, 0x01,
3107 0x00, 0x00, 0x38, 0xea,
3108 0xdf, 0xa2, 0x51, 0xb2,
3109 0x62, 0x60, 0x62, 0x60,
3110 0x4e, 0x4a, 0x2c, 0x62,
3111 0x60, 0x06, 0x08, 0xa0,
3112 0xb4, 0xfc, 0x7c, 0x80,
3113 0x00, 0x62, 0x60, 0x06,
3114 0x13, 0x00, 0x01, 0x94,
3115 0x94, 0x58, 0x04, 0x10,
3116 0x40, 0x00, 0x00, 0x00,
3117 0x00, 0xff, 0xff,
3119 const unsigned char kV3SIMDFrameData[] = {
3120 0x80, spdy_version_ch_, 0x00, 0x08,
3121 0x00, 0x00, 0x00, 0x2c,
3122 0x00, 0x00, 0x00, 0x01,
3123 0x38, 0xea, 0xe3, 0xc6,
3124 0xa7, 0xc2, 0x02, 0xe5,
3125 0x0e, 0x50, 0xc2, 0x4b,
3126 0x4a, 0x04, 0xe5, 0x0b,
3127 0x66, 0x80, 0x00, 0x4a,
3128 0xcb, 0xcf, 0x07, 0x08,
3129 0x20, 0x24, 0x0a, 0x20,
3130 0x80, 0x92, 0x12, 0x8b,
3131 0x00, 0x02, 0x08, 0x00,
3132 0x00, 0x00, 0xff, 0xff,
3135 SpdyHeadersIR headers_ir(1);
3136 headers_ir.SetHeader("bar", "foo");
3137 headers_ir.SetHeader("foo", "bar");
3138 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3139 const unsigned char* frame_data =
3140 reinterpret_cast<const unsigned char*>(frame->data());
3141 if (IsSpdy2()) {
3142 // Try comparing with SIMD version, if that fails, do a failing check
3143 // with pretty printing against non-SIMD version
3144 if (memcmp(frame_data,
3145 kV2SIMDFrameData,
3146 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3147 CompareCharArraysWithHexError(kDescription,
3148 frame_data,
3149 frame->size(),
3150 kV2FrameData,
3151 arraysize(kV2FrameData));
3153 } else if (IsSpdy3()) {
3154 if (memcmp(frame_data,
3155 kV3SIMDFrameData,
3156 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3157 CompareCharArraysWithHexError(kDescription,
3158 frame_data,
3159 frame->size(),
3160 kV3FrameData,
3161 arraysize(kV3FrameData));
3163 } else {
3164 // Deflate compression doesn't apply to HPACK.
3168 #endif // !defined(USE_SYSTEM_ZLIB)
3170 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3171 SpdyFramer framer(spdy_version_);
3174 const char kDescription[] = "WINDOW_UPDATE frame";
3175 const unsigned char kV3FrameData[] = { // Also applies for V2.
3176 0x80, spdy_version_ch_, 0x00, 0x09,
3177 0x00, 0x00, 0x00, 0x08,
3178 0x00, 0x00, 0x00, 0x01,
3179 0x00, 0x00, 0x00, 0x01,
3181 const unsigned char kH2FrameData[] = {
3182 0x00, 0x00, 0x04, 0x08,
3183 0x00, 0x00, 0x00, 0x00,
3184 0x01, 0x00, 0x00, 0x00,
3185 0x01,
3187 scoped_ptr<SpdyFrame> frame(
3188 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3189 if (IsHttp2()) {
3190 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3191 } else {
3192 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3197 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3198 const unsigned char kV3FrameData[] = { // Also applies for V2.
3199 0x80, spdy_version_ch_, 0x00, 0x09,
3200 0x00, 0x00, 0x00, 0x08,
3201 0x7f, 0xff, 0xff, 0xff,
3202 0x00, 0x00, 0x00, 0x01,
3204 const unsigned char kH2FrameData[] = {
3205 0x00, 0x00, 0x04, 0x08,
3206 0x00, 0x7f, 0xff, 0xff,
3207 0xff, 0x00, 0x00, 0x00,
3208 0x01,
3210 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3211 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3212 if (IsHttp2()) {
3213 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3214 } else {
3215 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3220 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3221 const unsigned char kV3FrameData[] = { // Also applies for V2.
3222 0x80, spdy_version_ch_, 0x00, 0x09,
3223 0x00, 0x00, 0x00, 0x08,
3224 0x00, 0x00, 0x00, 0x01,
3225 0x7f, 0xff, 0xff, 0xff,
3227 const unsigned char kH2FrameData[] = {
3228 0x00, 0x00, 0x04, 0x08,
3229 0x00, 0x00, 0x00, 0x00,
3230 0x01, 0x7f, 0xff, 0xff,
3231 0xff,
3233 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3234 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3235 if (IsHttp2()) {
3236 CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
3237 } else {
3238 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3243 TEST_P(SpdyFramerTest, SerializeBlocked) {
3244 if (spdy_version_ <= SPDY3) {
3245 return;
3248 SpdyFramer framer(spdy_version_);
3250 const char kDescription[] = "BLOCKED frame";
3251 const unsigned char kType = static_cast<unsigned char>(
3252 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3253 const unsigned char kFrameData[] = {
3254 0x00, 0x00, 0x00, kType, 0x00,
3255 0x00, 0x00, 0x00, 0x00,
3257 SpdyBlockedIR blocked_ir(0);
3258 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3259 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3262 TEST_P(SpdyFramerTest, CreateBlocked) {
3263 if (spdy_version_ <= SPDY3) {
3264 return;
3267 SpdyFramer framer(spdy_version_);
3269 const char kDescription[] = "BLOCKED frame";
3270 const SpdyStreamId kStreamId = 3;
3272 scoped_ptr<SpdySerializedFrame> frame_serialized(
3273 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3274 SpdyBlockedIR blocked_ir(kStreamId);
3275 scoped_ptr<SpdySerializedFrame> frame_created(
3276 framer.SerializeFrame(blocked_ir));
3278 CompareFrames(kDescription, *frame_serialized, *frame_created);
3281 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3282 if (spdy_version_ <= SPDY3) {
3283 return;
3287 // Test framing PUSH_PROMISE without padding.
3288 SpdyFramer framer(spdy_version_);
3289 framer.set_enable_compression(false);
3290 const char kDescription[] = "PUSH_PROMISE frame without padding";
3292 const unsigned char kFrameData[] = {
3293 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3294 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3295 0x2a, 0x00, 0x00, 0x00, // Stream 42
3296 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3297 0x61, 0x72, 0x03, 0x66, // ar.f
3298 0x6f, 0x6f, 0x00, 0x03, // oo@.
3299 0x66, 0x6f, 0x6f, 0x03, // foo.
3300 0x62, 0x61, 0x72, // bar
3303 SpdyPushPromiseIR push_promise(42, 57);
3304 push_promise.SetHeader("bar", "foo");
3305 push_promise.SetHeader("foo", "bar");
3306 scoped_ptr<SpdySerializedFrame> frame(
3307 framer.SerializePushPromise(push_promise));
3308 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3312 // Test framing PUSH_PROMISE with one byte of padding.
3313 SpdyFramer framer(spdy_version_);
3314 framer.set_enable_compression(false);
3315 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3317 const unsigned char kFrameData[] = {
3318 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3319 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3320 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3321 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3322 0x62, 0x61, 0x72, 0x03, // bar.
3323 0x66, 0x6f, 0x6f, 0x00, // foo@
3324 0x03, 0x66, 0x6f, 0x6f, // .foo
3325 0x03, 0x62, 0x61, 0x72, // .bar
3328 SpdyPushPromiseIR push_promise(42, 57);
3329 push_promise.set_padding_len(1);
3330 push_promise.SetHeader("bar", "foo");
3331 push_promise.SetHeader("foo", "bar");
3332 scoped_ptr<SpdySerializedFrame> frame(
3333 framer.SerializePushPromise(push_promise));
3334 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3338 // Test framing PUSH_PROMISE with 177 bytes of padding.
3339 SpdyFramer framer(spdy_version_);
3340 framer.set_enable_compression(false);
3341 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3343 const unsigned char kFrameData[] = {
3344 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3345 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3346 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3347 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3348 0x62, 0x61, 0x72, 0x03, // bar.
3349 0x66, 0x6f, 0x6f, 0x00, // foo@
3350 0x03, 0x66, 0x6f, 0x6f, // .foo
3351 0x03, 0x62, 0x61, 0x72, // .bar
3352 // Padding of 176 0x00(s).
3353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3370 SpdyPushPromiseIR push_promise(42, 57);
3371 push_promise.set_padding_len(177);
3372 push_promise.SetHeader("bar", "foo");
3373 push_promise.SetHeader("foo", "bar");
3374 scoped_ptr<SpdySerializedFrame> frame(
3375 framer.SerializePushPromise(push_promise));
3376 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3380 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
3381 if (spdy_version_ <= SPDY3) {
3382 return;
3385 SpdyFramer framer(spdy_version_);
3386 // Test case from https://crbug.com/464748.
3387 EXPECT_EQ(1u,
3388 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2039));
3389 EXPECT_EQ(2u,
3390 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2040));
3393 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3394 if (spdy_version_ <= SPDY3) {
3395 return;
3398 SpdyFramer framer(spdy_version_);
3399 framer.set_enable_compression(false);
3400 const char kDescription[] = "CONTINUATION frame";
3402 const unsigned char kFrameData[] = {
3403 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3404 0x04, 0x00, 0x00, 0x00, // end_headers = true
3405 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3406 0x61, 0x72, 0x03, 0x66, // ar.f
3407 0x6f, 0x6f, 0x00, 0x03, // oo@.
3408 0x66, 0x6f, 0x6f, 0x03, // foo.
3409 0x62, 0x61, 0x72, // bar
3412 SpdyContinuationIR continuation(42);
3413 continuation.SetHeader("bar", "foo");
3414 continuation.SetHeader("foo", "bar");
3415 continuation.set_end_headers(true);
3416 scoped_ptr<SpdySerializedFrame> frame(
3417 framer.SerializeContinuation(continuation));
3418 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3421 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3422 if (spdy_version_ <= SPDY3) {
3423 return;
3427 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3428 // padding, cannot hold all the data payload, which is overflowed to the
3429 // consecutive CONTINUATION frame.
3430 SpdyFramer framer(spdy_version_);
3431 framer.set_enable_compression(false);
3432 const char kDescription[] =
3433 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3435 const unsigned char kPartialPushPromiseFrameData[] = {
3436 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3437 0x08, 0x00, 0x00, 0x00, // PADDED
3438 0x2a, 0x00, 0x00, 0x00, // Stream 42
3439 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3440 0x78, 0x78, 0x78, 0x7f, // xxx.
3441 0x81, 0x07, 0x78, 0x78, // ..xx
3442 0x78, 0x78, 0x78, 0x78, // xxxx
3443 0x78, 0x78, 0x78, 0x78, // xxxx
3444 0x78, 0x78, 0x78, 0x78, // xxxx
3445 0x78, 0x78, 0x78, 0x78, // xxxx
3446 0x78, 0x78, 0x78, 0x78, // xxxx
3447 0x78, 0x78, 0x78, 0x78, // xxxx
3448 0x78, 0x78, 0x78, 0x78, // xxxx
3449 0x78, 0x78, 0x78, 0x78, // xxxx
3450 0x78, 0x78, 0x78, 0x78, // xxxx
3451 0x78, 0x78, 0x78, 0x78, // xxxx
3452 0x78, 0x78, 0x78, 0x78, // xxxx
3453 0x78, 0x78, 0x78, 0x78, // xxxx
3454 0x78, 0x78, 0x78, 0x78, // xxxx
3455 0x78, 0x78, 0x78, 0x78, // xxxx
3456 0x78, 0x78, 0x78, 0x78, // xxxx
3457 0x78, 0x78, 0x78, 0x78, // xxxx
3458 0x78, 0x78, 0x78, 0x78, // xxxx
3459 0x78, 0x78, 0x78, 0x78, // xxxx
3460 0x78, 0x78, 0x78, 0x78, // xxxx
3461 0x78, 0x78, 0x78, 0x78, // xxxx
3462 0x78, 0x78, // xx
3465 const unsigned char kContinuationFrameData[] = {
3466 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3467 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3468 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3469 0x78, 0x78, 0x78, 0x78, // xxxx
3470 0x78, 0x78, 0x78, 0x78, // xxxx
3471 0x78, 0x78, 0x78, 0x78, // xxxx
3472 0x78, 0x78, 0x78, 0x78, // xxxx
3473 0x78, 0x78,
3476 SpdyPushPromiseIR push_promise(42, 57);
3477 push_promise.set_padding_len(1);
3478 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3479 push_promise.SetHeader("xxx", big_value);
3480 scoped_ptr<SpdySerializedFrame> frame(
3481 framer.SerializePushPromise(push_promise));
3483 // The entire frame should look like below:
3484 // Name Length in Byte
3485 // ------------------------------------------- Begin of PUSH_PROMISE frame
3486 // PUSH_PROMISE header 9
3487 // Pad length field 1
3488 // Promised stream 4
3489 // Length field of key 2
3490 // Content of key 3
3491 // Length field of value 3
3492 // Part of big_value 16361
3493 // ------------------------------------------- Begin of CONTINUATION frame
3494 // CONTINUATION header 9
3495 // Remaining of big_value 22
3496 // ------------------------------------------- End
3498 // Length of everything listed above except big_value.
3499 int len_non_data_payload = 31;
3500 EXPECT_EQ(
3501 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3502 frame->size());
3504 // Partially compare the PUSH_PROMISE frame against the template.
3505 const unsigned char* frame_data =
3506 reinterpret_cast<const unsigned char*>(frame->data());
3507 CompareCharArraysWithHexError(kDescription,
3508 frame_data,
3509 arraysize(kPartialPushPromiseFrameData),
3510 kPartialPushPromiseFrameData,
3511 arraysize(kPartialPushPromiseFrameData));
3513 // Compare the CONTINUATION frame against the template.
3514 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3515 CompareCharArraysWithHexError(kDescription,
3516 frame_data,
3517 arraysize(kContinuationFrameData),
3518 kContinuationFrameData,
3519 arraysize(kContinuationFrameData));
3523 TEST_P(SpdyFramerTest, CreateAltSvc) {
3524 if (spdy_version_ <= SPDY3) {
3525 return;
3528 SpdyFramer framer(spdy_version_);
3530 const char kDescription[] = "ALTSVC frame";
3531 const char kType = static_cast<unsigned char>(
3532 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3533 const unsigned char kFrameData[] = {
3534 0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
3535 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h',
3536 'o', 's', 't', ':', '4', '4', '3', '"', ';', ' ', 'm', 'a',
3537 '=', '5', ',', 'p', '%', '2', '2', '%', '3', 'D', 'i', '%',
3538 '3', 'A', 'd', '=', '"', 'h', '_', '\\', '\\', 'o', '\\', '"',
3539 's', 't', ':', '1', '2', '3', '"', ';', ' ', 'm', 'a', '=',
3540 '4', '2', ';', ' ', 'p', '=', '0', '.', '2', '0',
3542 SpdyAltSvcIR altsvc_ir(3);
3543 altsvc_ir.set_origin("origin");
3544 altsvc_ir.add_altsvc(
3545 SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0));
3546 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
3547 "p\"=i:d", "h_\\o\"st", 123, 42, 0.2));
3548 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3549 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3552 TEST_P(SpdyFramerTest, CreatePriority) {
3553 if (spdy_version_ <= SPDY3) {
3554 return;
3557 SpdyFramer framer(spdy_version_);
3559 const char kDescription[] = "PRIORITY frame";
3560 const unsigned char kType = static_cast<unsigned char>(
3561 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3562 const unsigned char kFrameData[] = {
3563 0x00, 0x00, 0x05, kType, 0x00,
3564 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3565 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3566 0x10, // Weight = 16
3568 SpdyPriorityIR priority_ir(2, 1, 16, true);
3569 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3570 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3571 SpdyPriorityIR priority2(2);
3572 priority2.set_parent_stream_id(1);
3573 priority2.set_weight(16);
3574 priority2.set_exclusive(true);
3575 frame.reset(framer.SerializeFrame(priority2));
3576 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3579 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3580 if (spdy_version_ > SPDY3) {
3581 // SYN_STREAM not supported in SPDY>3
3582 return;
3584 SpdyFramer framer(spdy_version_);
3585 SpdySynStreamIR syn_stream(1);
3586 syn_stream.set_priority(1);
3587 syn_stream.SetHeader("aa", "vv");
3588 syn_stream.SetHeader("bb", "ww");
3589 SpdyHeaderBlock headers = syn_stream.header_block();
3590 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3591 EXPECT_TRUE(control_frame.get() != NULL);
3592 TestSpdyVisitor visitor(spdy_version_);
3593 visitor.use_compression_ = true;
3594 visitor.SimulateInFramer(
3595 reinterpret_cast<unsigned char*>(control_frame->data()),
3596 control_frame->size());
3597 EXPECT_EQ(1, visitor.syn_frame_count_);
3598 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3601 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3602 if (spdy_version_ > SPDY3) {
3603 return;
3605 SpdyFramer framer(spdy_version_);
3606 SpdySynReplyIR syn_reply(1);
3607 syn_reply.SetHeader("alpha", "beta");
3608 syn_reply.SetHeader("gamma", "delta");
3609 SpdyHeaderBlock headers = syn_reply.header_block();
3610 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3611 EXPECT_TRUE(control_frame.get() != NULL);
3612 TestSpdyVisitor visitor(spdy_version_);
3613 visitor.use_compression_ = true;
3614 visitor.SimulateInFramer(
3615 reinterpret_cast<unsigned char*>(control_frame->data()),
3616 control_frame->size());
3617 if (IsHttp2()) {
3618 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3619 EXPECT_EQ(1, visitor.headers_frame_count_);
3620 } else {
3621 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3622 EXPECT_EQ(0, visitor.headers_frame_count_);
3624 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3627 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3628 SpdyFramer framer(spdy_version_);
3629 SpdyHeadersIR headers_ir(1);
3630 headers_ir.SetHeader("alpha", "beta");
3631 headers_ir.SetHeader("gamma", "delta");
3632 SpdyHeaderBlock headers = headers_ir.header_block();
3633 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3634 EXPECT_TRUE(control_frame.get() != NULL);
3635 TestSpdyVisitor visitor(spdy_version_);
3636 visitor.use_compression_ = true;
3637 visitor.SimulateInFramer(
3638 reinterpret_cast<unsigned char*>(control_frame->data()),
3639 control_frame->size());
3640 EXPECT_EQ(1, visitor.headers_frame_count_);
3641 // control_frame_header_data_count_ depends on the random sequence
3642 // produced by rand(), so adding, removing or running single tests
3643 // alters this value. The best we can do is assert that it happens
3644 // at least twice.
3645 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3646 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3647 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3648 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3651 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3652 SpdyFramer framer(spdy_version_);
3653 SpdyHeadersIR headers_ir(1);
3654 headers_ir.set_fin(true);
3655 headers_ir.SetHeader("alpha", "beta");
3656 headers_ir.SetHeader("gamma", "delta");
3657 SpdyHeaderBlock headers = headers_ir.header_block();
3658 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3659 EXPECT_TRUE(control_frame.get() != NULL);
3660 TestSpdyVisitor visitor(spdy_version_);
3661 visitor.use_compression_ = true;
3662 visitor.SimulateInFramer(
3663 reinterpret_cast<unsigned char*>(control_frame->data()),
3664 control_frame->size());
3665 EXPECT_EQ(1, visitor.headers_frame_count_);
3666 // control_frame_header_data_count_ depends on the random sequence
3667 // produced by rand(), so adding, removing or running single tests
3668 // alters this value. The best we can do is assert that it happens
3669 // at least twice.
3670 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3671 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3672 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3673 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3676 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3677 if (spdy_version_ > SPDY3) {
3678 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3679 return;
3681 // First find the size of the header value in order to just reach the control
3682 // frame max size.
3683 SpdyFramer framer(spdy_version_);
3684 framer.set_enable_compression(false);
3685 SpdySynStreamIR syn_stream(1);
3686 syn_stream.set_priority(1);
3687 syn_stream.SetHeader("aa", "");
3688 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3689 const size_t kBigValueSize =
3690 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3692 // Create a frame at exactly that size.
3693 string big_value(kBigValueSize, 'x');
3694 syn_stream.SetHeader("aa", big_value);
3695 control_frame.reset(framer.SerializeSynStream(syn_stream));
3696 EXPECT_TRUE(control_frame.get() != NULL);
3697 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3698 control_frame->size());
3700 TestSpdyVisitor visitor(spdy_version_);
3701 visitor.SimulateInFramer(
3702 reinterpret_cast<unsigned char*>(control_frame->data()),
3703 control_frame->size());
3704 EXPECT_TRUE(visitor.header_buffer_valid_);
3705 EXPECT_EQ(0, visitor.error_count_);
3706 EXPECT_EQ(1, visitor.syn_frame_count_);
3707 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3708 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3709 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3712 TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
3713 if (spdy_version_ > SPDY3) {
3714 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3715 return;
3717 if (spdy_version_ < SPDY3) {
3718 // Since SPDY/2 uses 16 bit header field lengths, one cannot easily create a
3719 // header frame of maximum size.
3720 return;
3722 // First find the size of the header value in order to just reach the control
3723 // frame max size.
3724 SpdyFramer framer(spdy_version_);
3725 framer.set_enable_compression(false);
3726 SpdySynStreamIR syn_stream(1);
3727 syn_stream.SetHeader("aa", "");
3728 syn_stream.set_priority(1);
3729 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3730 const size_t kBigValueSize =
3731 SpdyConstants::GetFrameMaximumSize(spdy_version_) - control_frame->size();
3733 // Create a frame at exatly that size.
3734 string big_value(kBigValueSize, 'x');
3735 syn_stream.SetHeader("aa", big_value);
3736 // Upstream branches here and wraps HTTP/2 with EXPECT_DEBUG_DFATAL. We
3737 // neither support that in Chromium, nor do we use the same DFATAL (see
3738 // SpdyFrameBuilder::WriteFramePrefix()).
3739 control_frame.reset(framer.SerializeSynStream(syn_stream));
3741 EXPECT_TRUE(control_frame.get() != NULL);
3742 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_),
3743 control_frame->size());
3745 TestSpdyVisitor visitor(spdy_version_);
3746 visitor.SimulateInFramer(
3747 reinterpret_cast<unsigned char*>(control_frame->data()),
3748 control_frame->size());
3749 EXPECT_TRUE(visitor.header_buffer_valid_);
3750 EXPECT_EQ(0, visitor.error_count_);
3751 EXPECT_EQ(1, visitor.syn_frame_count_);
3754 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3755 if (spdy_version_ <= SPDY3) {
3756 return;
3758 SpdyFramer framer(spdy_version_);
3759 framer.set_enable_compression(false);
3760 SpdyHeadersIR headers(1);
3761 headers.set_padding_len(256);
3763 // Exact payload length will change with HPACK, but this should be long
3764 // enough to cause an overflow.
3765 const size_t kBigValueSize = kControlFrameSizeLimit;
3766 string big_value(kBigValueSize, 'x');
3767 headers.SetHeader("aa", big_value);
3768 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3769 EXPECT_TRUE(control_frame.get() != NULL);
3770 EXPECT_GT(control_frame->size(),
3771 TestSpdyVisitor::sent_control_frame_max_size());
3773 TestSpdyVisitor visitor(spdy_version_);
3774 visitor.SimulateInFramer(
3775 reinterpret_cast<unsigned char*>(control_frame->data()),
3776 control_frame->size());
3777 EXPECT_TRUE(visitor.header_buffer_valid_);
3778 EXPECT_EQ(0, visitor.error_count_);
3779 EXPECT_EQ(1, visitor.headers_frame_count_);
3780 EXPECT_EQ(16, visitor.continuation_count_);
3781 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3784 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3785 if (spdy_version_ <= SPDY3) {
3786 return;
3788 SpdyFramer framer(spdy_version_);
3789 framer.set_enable_compression(false);
3790 SpdyPushPromiseIR push_promise(1, 2);
3791 push_promise.set_padding_len(256);
3793 // Exact payload length will change with HPACK, but this should be long
3794 // enough to cause an overflow.
3795 const size_t kBigValueSize = kControlFrameSizeLimit;
3796 string big_value(kBigValueSize, 'x');
3797 push_promise.SetHeader("aa", big_value);
3798 scoped_ptr<SpdyFrame> control_frame(
3799 framer.SerializePushPromise(push_promise));
3800 EXPECT_TRUE(control_frame.get() != NULL);
3801 EXPECT_GT(control_frame->size(),
3802 TestSpdyVisitor::sent_control_frame_max_size());
3804 TestSpdyVisitor visitor(spdy_version_);
3805 visitor.SimulateInFramer(
3806 reinterpret_cast<unsigned char*>(control_frame->data()),
3807 control_frame->size());
3808 EXPECT_TRUE(visitor.header_buffer_valid_);
3809 EXPECT_EQ(0, visitor.error_count_);
3810 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3811 EXPECT_EQ(16, visitor.continuation_count_);
3812 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3815 // Check that the framer stops delivering header data chunks once the visitor
3816 // declares it doesn't want any more. This is important to guard against
3817 // "zip bomb" types of attacks.
3818 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3819 const size_t kHeaderBufferChunks = 4;
3820 const size_t kHeaderBufferSize =
3821 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3822 const size_t kBigValueSize = kHeaderBufferSize * 2;
3823 string big_value(kBigValueSize, 'x');
3824 SpdyFramer framer(spdy_version_);
3825 SpdyHeadersIR headers(1);
3826 headers.set_priority(1);
3827 headers.set_fin(true);
3828 headers.SetHeader("aa", big_value);
3829 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3830 EXPECT_TRUE(control_frame.get() != NULL);
3831 TestSpdyVisitor visitor(spdy_version_);
3832 visitor.set_header_buffer_size(kHeaderBufferSize);
3833 visitor.use_compression_ = true;
3834 visitor.SimulateInFramer(
3835 reinterpret_cast<unsigned char*>(control_frame->data()),
3836 control_frame->size());
3837 EXPECT_FALSE(visitor.header_buffer_valid_);
3838 EXPECT_EQ(1, visitor.error_count_);
3839 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3840 visitor.framer_.error_code())
3841 << SpdyFramer::ErrorCodeToString(framer.error_code());
3843 // The framer should have stoped delivering chunks after the visitor
3844 // signaled "stop" by returning false from OnControlFrameHeaderData().
3846 // control_frame_header_data_count_ depends on the random sequence
3847 // produced by rand(), so adding, removing or running single tests
3848 // alters this value. The best we can do is assert that it happens
3849 // at least kHeaderBufferChunks + 1.
3850 EXPECT_LE(kHeaderBufferChunks + 1,
3851 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3852 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3854 // The framer should not have sent half-close to the visitor.
3855 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3858 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3859 if (spdy_version_ > SPDY3) {
3860 // Deflate compression doesn't apply to HPACK.
3861 return;
3863 SpdyFramer framer(spdy_version_);
3864 framer.set_enable_compression(false);
3865 // Construct a SYN_STREAM control frame without compressing the header block,
3866 // and have the framer try to decompress it. This will cause the framer to
3867 // deal with a decompression error.
3868 SpdySynStreamIR syn_stream(1);
3869 syn_stream.set_priority(1);
3870 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3871 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3872 TestSpdyVisitor visitor(spdy_version_);
3873 visitor.use_compression_ = true;
3874 visitor.SimulateInFramer(
3875 reinterpret_cast<unsigned char*>(control_frame->data()),
3876 control_frame->size());
3877 EXPECT_EQ(1, visitor.error_count_);
3878 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3879 << SpdyFramer::ErrorCodeToString(framer.error_code());
3880 EXPECT_EQ(0u, visitor.header_buffer_length_);
3883 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3884 SpdyFramer framer(spdy_version_);
3885 // Create a GoAway frame that has a few extra bytes at the end.
3886 // We create enough overhead to overflow the framer's control frame buffer.
3887 ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
3888 const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
3889 const unsigned char kV3FrameData[] = { // Also applies for V2.
3890 0x80, spdy_version_ch_, 0x00, 0x07,
3891 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
3892 0x00, 0x00, 0x00, 0x00, // Stream ID
3893 0x00, 0x00, 0x00, 0x00, // Status
3896 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3897 // since it may carry opaque data. Verify that minimal length is tested.
3898 ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
3899 const size_t less_than_min_length =
3900 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3901 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3902 const unsigned char kH2FrameData[] = {
3903 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
3904 0x00, 0x00, 0x00, 0x00,
3905 0x00, 0x00, 0x00, 0x00, // Stream Id
3906 0x00, 0x00, 0x00, 0x00, // Status
3907 0x00,
3909 const size_t pad_length =
3910 length + framer.GetControlFrameHeaderSize() -
3911 (IsHttp2() ? sizeof(kH2FrameData) : sizeof(kV3FrameData));
3912 string pad(pad_length, 'A');
3913 TestSpdyVisitor visitor(spdy_version_);
3915 if (IsHttp2()) {
3916 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3917 } else {
3918 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3920 visitor.SimulateInFramer(
3921 reinterpret_cast<const unsigned char*>(pad.c_str()),
3922 pad.length());
3924 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3925 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3926 visitor.framer_.error_code())
3927 << SpdyFramer::ErrorCodeToString(framer.error_code());
3928 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3931 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3932 SpdyFramer framer(spdy_version_);
3933 SpdySettingsIR settings_ir;
3934 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3935 SetFrameLength(control_frame.get(), 0, spdy_version_);
3936 TestSpdyVisitor visitor(spdy_version_);
3937 visitor.use_compression_ = false;
3938 visitor.SimulateInFramer(
3939 reinterpret_cast<unsigned char*>(control_frame->data()),
3940 framer.GetControlFrameHeaderSize());
3941 if (spdy_version_ <= SPDY3) {
3942 // Should generate an error, since zero-len settings frames are unsupported.
3943 EXPECT_EQ(1, visitor.error_count_);
3944 } else {
3945 // Zero-len settings frames are permitted as of HTTP/2.
3946 EXPECT_EQ(0, visitor.error_count_);
3950 // Tests handling of SETTINGS frames with invalid length.
3951 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3952 SpdyFramer framer(spdy_version_);
3953 SpdySettingsIR settings_ir;
3955 // Add a setting to pad the frame so that we don't get a buffer overflow when
3956 // calling SimulateInFramer() below.
3957 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3958 false,
3959 false,
3960 0x00000002);
3961 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3962 const size_t kNewLength = 14;
3963 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3964 TestSpdyVisitor visitor(spdy_version_);
3965 visitor.use_compression_ = false;
3966 visitor.SimulateInFramer(
3967 reinterpret_cast<unsigned char*>(control_frame->data()),
3968 framer.GetControlFrameHeaderSize() + kNewLength);
3969 // Should generate an error, since its not possible to have a
3970 // settings frame of length kNewLength.
3971 EXPECT_EQ(1, visitor.error_count_);
3974 // Tests handling of SETTINGS frames larger than the frame buffer size.
3975 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3976 SpdyFramer framer(spdy_version_);
3977 SpdySettingsIR settings_ir;
3978 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3979 false, // persist
3980 false, // persisted
3982 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3983 false, // persist
3984 false, // persisted
3986 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3987 false, // persist
3988 false, // persisted
3991 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3992 EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame->size());
3993 TestSpdyVisitor visitor(spdy_version_);
3994 visitor.use_compression_ = false;
3996 // Read all at once.
3997 visitor.SimulateInFramer(
3998 reinterpret_cast<unsigned char*>(control_frame->data()),
3999 control_frame->size());
4000 EXPECT_EQ(0, visitor.error_count_);
4001 EXPECT_EQ(3, visitor.setting_count_);
4002 if (spdy_version_ > SPDY3) {
4003 EXPECT_EQ(1, visitor.settings_ack_sent_);
4006 // Read data in small chunks.
4007 size_t framed_data = 0;
4008 size_t unframed_data = control_frame->size();
4009 size_t kReadChunkSize = 5; // Read five bytes at a time.
4010 while (unframed_data > 0) {
4011 size_t to_read = std::min(kReadChunkSize, unframed_data);
4012 visitor.SimulateInFramer(
4013 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
4014 to_read);
4015 unframed_data -= to_read;
4016 framed_data += to_read;
4018 EXPECT_EQ(0, visitor.error_count_);
4019 EXPECT_EQ(3 * 2, visitor.setting_count_);
4020 if (spdy_version_ > SPDY3) {
4021 EXPECT_EQ(2, visitor.settings_ack_sent_);
4025 // Tests handling of SETTINGS frame with duplicate entries.
4026 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
4027 SpdyFramer framer(spdy_version_);
4029 const unsigned char kV2FrameData[] = {
4030 0x80, spdy_version_ch_, 0x00, 0x04,
4031 0x00, 0x00, 0x00, 0x1C,
4032 0x00, 0x00, 0x00, 0x03,
4033 0x01, 0x00, 0x00, 0x00, // 1st Setting
4034 0x00, 0x00, 0x00, 0x02,
4035 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
4036 0x00, 0x00, 0x00, 0x03,
4037 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4038 0x00, 0x00, 0x00, 0x03,
4040 const unsigned char kV3FrameData[] = {
4041 0x80, spdy_version_ch_, 0x00, 0x04,
4042 0x00, 0x00, 0x00, 0x1C,
4043 0x00, 0x00, 0x00, 0x03,
4044 0x00, 0x00, 0x00, 0x01, // 1st Setting
4045 0x00, 0x00, 0x00, 0x02,
4046 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
4047 0x00, 0x00, 0x00, 0x03,
4048 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
4049 0x00, 0x00, 0x00, 0x03,
4051 const unsigned char kH2FrameData[] = {
4052 0x00, 0x00, 0x12, 0x04,
4053 0x00, 0x00, 0x00, 0x00,
4054 0x00, 0x00, 0x01, // 1st Setting
4055 0x00, 0x00, 0x00, 0x02,
4056 0x00, 0x01, // 2nd (duplicate) Setting
4057 0x00, 0x00, 0x00, 0x03,
4058 0x00, 0x03, // 3rd (unprocessed) Setting
4059 0x00, 0x00, 0x00, 0x03,
4062 TestSpdyVisitor visitor(spdy_version_);
4063 visitor.use_compression_ = false;
4064 if (IsSpdy2()) {
4065 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4066 } else if (IsSpdy3()) {
4067 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4068 } else {
4069 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4072 if (!IsHttp2()) {
4073 EXPECT_EQ(1, visitor.setting_count_);
4074 EXPECT_EQ(1, visitor.error_count_);
4075 } else {
4076 // In HTTP/2, duplicate settings are allowed;
4077 // each setting replaces the previous value for that setting.
4078 EXPECT_EQ(3, visitor.setting_count_);
4079 EXPECT_EQ(0, visitor.error_count_);
4080 EXPECT_EQ(1, visitor.settings_ack_sent_);
4084 // Tests handling of SETTINGS frame with a setting we don't recognize.
4085 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
4086 SpdyFramer framer(spdy_version_);
4088 const unsigned char kV2FrameData[] = {
4089 0x80, spdy_version_ch_, 0x00, 0x04,
4090 0x00, 0x00, 0x00, 0x1C,
4091 0x00, 0x00, 0x00, 0x01,
4092 0x10, 0x00, 0x00, 0x00, // 1st Setting
4093 0x00, 0x00, 0x00, 0x02,
4095 const unsigned char kV3FrameData[] = {
4096 0x80, spdy_version_ch_, 0x00, 0x04,
4097 0x00, 0x00, 0x00, 0x1C,
4098 0x00, 0x00, 0x00, 0x01,
4099 0x00, 0x00, 0x00, 0x10, // 1st Setting
4100 0x00, 0x00, 0x00, 0x02,
4102 const unsigned char kH2FrameData[] = {
4103 0x00, 0x00, 0x06, 0x04,
4104 0x00, 0x00, 0x00, 0x00,
4105 0x00, 0x00, 0x10, // 1st Setting
4106 0x00, 0x00, 0x00, 0x02,
4109 TestSpdyVisitor visitor(spdy_version_);
4110 visitor.use_compression_ = false;
4111 if (IsSpdy2()) {
4112 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4113 } else if (IsSpdy3()) {
4114 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4115 } else {
4116 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4119 if (!IsHttp2()) {
4120 EXPECT_EQ(0, visitor.setting_count_);
4121 EXPECT_EQ(1, visitor.error_count_);
4122 } else {
4123 // In HTTP/2, we ignore unknown settings because of extensions.
4124 EXPECT_EQ(0, visitor.setting_count_);
4125 EXPECT_EQ(0, visitor.error_count_);
4129 // Tests handling of SETTINGS frame with entries out of order.
4130 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
4131 SpdyFramer framer(spdy_version_);
4133 const unsigned char kV2FrameData[] = {
4134 0x80, spdy_version_ch_, 0x00, 0x04,
4135 0x00, 0x00, 0x00, 0x1C,
4136 0x00, 0x00, 0x00, 0x03,
4137 0x02, 0x00, 0x00, 0x00, // 1st Setting
4138 0x00, 0x00, 0x00, 0x02,
4139 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
4140 0x00, 0x00, 0x00, 0x03,
4141 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
4142 0x00, 0x00, 0x00, 0x03,
4144 const unsigned char kV3FrameData[] = {
4145 0x80, spdy_version_ch_, 0x00, 0x04,
4146 0x00, 0x00, 0x00, 0x1C,
4147 0x00, 0x00, 0x00, 0x03,
4148 0x00, 0x00, 0x00, 0x02, // 1st Setting
4149 0x00, 0x00, 0x00, 0x02,
4150 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4151 0x00, 0x00, 0x00, 0x03,
4152 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4153 0x00, 0x00, 0x00, 0x03,
4155 const unsigned char kH2FrameData[] = {
4156 0x00, 0x00, 0x12, 0x04,
4157 0x00, 0x00, 0x00, 0x00,
4158 0x00, 0x00, 0x02, // 1st Setting
4159 0x00, 0x00, 0x00, 0x02,
4160 0x00, 0x01, // 2nd (out of order) Setting
4161 0x00, 0x00, 0x00, 0x03,
4162 0x00, 0x03, // 3rd (unprocessed) Setting
4163 0x00, 0x00, 0x00, 0x03,
4166 TestSpdyVisitor visitor(spdy_version_);
4167 visitor.use_compression_ = false;
4168 if (IsSpdy2()) {
4169 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4170 } else if (IsSpdy3()) {
4171 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4172 } else {
4173 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
4176 if (!IsHttp2()) {
4177 EXPECT_EQ(1, visitor.setting_count_);
4178 EXPECT_EQ(1, visitor.error_count_);
4179 } else {
4180 // In HTTP/2, settings are allowed in any order.
4181 EXPECT_EQ(3, visitor.setting_count_);
4182 EXPECT_EQ(0, visitor.error_count_);
4186 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4187 if (spdy_version_ <= SPDY3) {
4188 return;
4190 SpdyFramer framer(spdy_version_);
4192 const unsigned char kFrameData[] = {
4193 0x00, 0x00, 0x00, 0x04, 0x01,
4194 0x00, 0x00, 0x00, 0x00,
4197 TestSpdyVisitor visitor(spdy_version_);
4198 visitor.use_compression_ = false;
4199 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4201 EXPECT_EQ(0, visitor.error_count_);
4202 EXPECT_EQ(0, visitor.setting_count_);
4203 EXPECT_EQ(1, visitor.settings_ack_received_);
4206 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4207 if (spdy_version_ <= SPDY3) {
4208 return;
4211 const int kPaddingLen = 119;
4212 const char data_payload[] = "hello";
4214 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4215 SpdyFramer framer(spdy_version_);
4216 framer.set_visitor(&visitor);
4218 SpdyDataIR data_ir(1, data_payload);
4219 data_ir.set_padding_len(kPaddingLen);
4220 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4221 ASSERT_TRUE(frame.get() != NULL);
4223 int bytes_consumed = 0;
4225 // Send the frame header.
4226 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4227 kPaddingLen + strlen(data_payload),
4228 false));
4229 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4230 framer.ProcessInput(frame->data(),
4231 framer.GetDataFrameMinimumSize()));
4232 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4233 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4234 bytes_consumed += framer.GetDataFrameMinimumSize();
4236 // Send the padding length field.
4237 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
4238 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4239 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4240 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4241 bytes_consumed += 1;
4243 // Send the first two bytes of the data payload, i.e., "he".
4244 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4245 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4246 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4247 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4248 bytes_consumed += 2;
4250 // Send the rest three bytes of the data payload, i.e., "llo".
4251 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4252 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4253 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4254 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4255 bytes_consumed += 3;
4257 // Send the first 100 bytes of the padding payload.
4258 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
4259 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4260 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4261 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4262 bytes_consumed += 100;
4264 // Send rest of the padding payload.
4265 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
4266 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4267 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READY_FOR_FRAME);
4268 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4271 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4272 SpdyFramer framer(spdy_version_);
4273 scoped_ptr<SpdyFrame> control_frame(
4274 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4275 TestSpdyVisitor visitor(spdy_version_);
4276 visitor.SimulateInFramer(
4277 reinterpret_cast<unsigned char*>(control_frame->data()),
4278 control_frame->size());
4279 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4280 EXPECT_EQ(2, visitor.last_window_update_delta_);
4283 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4284 if (!IsSpdy3()) {
4285 return;
4287 SpdyFramer framer(spdy_version_);
4288 const unsigned char kV3FrameData[] = { // Also applies for V2.
4289 0x80, spdy_version_ch_, 0x00, 0x0A,
4290 0x00, 0x00, 0x00, 0x33,
4291 0x00, 0x03, 0x00, 0x00,
4292 0x00, 0x05, 'p', 'r',
4293 'o', 'o', 'f', 0x00,
4294 0x00, 0x00, 0x06, 'a',
4295 ' ', 'c', 'e', 'r',
4296 't', 0x00, 0x00, 0x00,
4297 0x0C, 'a', 'n', 'o',
4298 't', 'h', 'e', 'r',
4299 ' ', 'c', 'e', 'r',
4300 't', 0x00, 0x00, 0x00,
4301 0x0A, 'f', 'i', 'n',
4302 'a', 'l', ' ', 'c',
4303 'e', 'r', 't',
4305 TestSpdyVisitor visitor(spdy_version_);
4306 visitor.use_compression_ = false;
4307 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4308 EXPECT_EQ(0, visitor.error_count_);
4311 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4312 if (!IsSpdy3()) {
4313 return;
4315 SpdyFramer framer(spdy_version_);
4316 const unsigned char kV3FrameData[] = { // Also applies for V2.
4317 0x80, spdy_version_ch_, 0x00, 0x0A,
4318 0x00, 0x00, 0x00, 0x33,
4319 0x00, 0x03, 0x00, 0x00,
4320 0x00, 0x05, 'p', 'r',
4321 'o', 'o', 'f', 0x00,
4322 0x00, 0x00, 0x06, 'a',
4323 ' ', 'c', 'e', 'r',
4324 't', 0x00, 0x00, 0x00,
4325 0x0C, 'a', 'n', 'o',
4326 't', 'h', 'e', 'r',
4327 ' ', 'c', 'e', 'r',
4328 't', 0x00, 0x00, 0x00,
4329 0x0A, 'f', 'i', 'n',
4330 'a', 'l', ' ', 'c',
4331 'e', 'r', 't',
4333 TestSpdyVisitor visitor(spdy_version_);
4334 visitor.use_compression_ = false;
4335 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4336 arraysize(kV3FrameData));
4337 scoped_ptr<SpdyFrame> control_frame(
4338 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4339 multiple_frame_data.append(string(control_frame->data(),
4340 control_frame->size()));
4341 visitor.SimulateInFramer(
4342 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4343 multiple_frame_data.length());
4344 EXPECT_EQ(0, visitor.error_count_);
4345 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4346 EXPECT_EQ(2, visitor.last_window_update_delta_);
4349 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4350 if (spdy_version_ <= SPDY3) {
4351 return;
4354 SpdyFramer framer(spdy_version_);
4355 SpdyPushPromiseIR push_promise(42, 57);
4356 push_promise.SetHeader("foo", "bar");
4357 push_promise.SetHeader("bar", "foofoo");
4358 SpdyHeaderBlock headers = push_promise.header_block();
4359 scoped_ptr<SpdySerializedFrame> frame(
4360 framer.SerializePushPromise(push_promise));
4361 EXPECT_TRUE(frame.get() != NULL);
4362 TestSpdyVisitor visitor(spdy_version_);
4363 visitor.use_compression_ = true;
4364 visitor.SimulateInFramer(
4365 reinterpret_cast<unsigned char*>(frame->data()),
4366 frame->size());
4367 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4368 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4369 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4372 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4373 if (spdy_version_ <= SPDY3) {
4374 return;
4377 const unsigned char kInput[] = {
4378 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4379 0x00, 0x00, 0x00, 0x01, // Stream 1
4380 0x03, // Padding of 3.
4381 0x00, 0x06, 'c', 'o',
4382 'o', 'k', 'i', 'e',
4383 0x07, 'f', 'o', 'o',
4384 '=', 'b', 'a', 'r',
4385 0x00, 0x00, 0x00,
4387 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4388 0x00, 0x00, 0x00, 0x01, // Stream 1
4389 0x00, 0x06, 'c', 'o',
4390 'o', 'k', 'i', 'e',
4391 0x08, 'b', 'a', 'z',
4392 '=', 'b', 'i', 'n',
4393 'g', 0x00, 0x06, 'c',
4395 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4396 0x00, 0x00, 0x00, 0x01, // Stream 1
4397 'o', 'o', 'k', 'i',
4398 'e', 0x00, 0x00, 0x04,
4399 'n', 'a', 'm', 'e',
4400 0x05, 'v', 'a', 'l',
4401 'u', 'e',
4404 TestSpdyVisitor visitor(spdy_version_);
4405 visitor.SimulateInFramer(kInput, sizeof(kInput));
4407 EXPECT_EQ(0, visitor.error_count_);
4408 EXPECT_EQ(1, visitor.headers_frame_count_);
4409 EXPECT_EQ(2, visitor.continuation_count_);
4410 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4411 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4413 EXPECT_THAT(visitor.headers_,
4414 testing::ElementsAre(
4415 testing::Pair("cookie", "foo=bar; baz=bing; "),
4416 testing::Pair("name", "value")));
4419 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4420 if (spdy_version_ <= SPDY3) {
4421 return;
4424 const unsigned char kInput[] = {
4425 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4426 0x00, 0x00, 0x00, 0x01, // Stream 1
4427 0x00, 0x06, 'c', 'o',
4428 'o', 'k', 'i', 'e',
4429 0x07, 'f', 'o', 'o',
4430 '=', 'b', 'a', 'r',
4432 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4433 0x00, 0x00, 0x00, 0x01, // Stream 1
4434 0x00, 0x06, 'c', 'o',
4435 'o', 'k', 'i', 'e',
4436 0x08, 'b', 'a', 'z',
4437 '=', 'b', 'i', 'n',
4438 'g', 0x00, 0x06, 'c',
4440 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4441 0x00, 0x00, 0x00, 0x01, // Stream 1
4442 'o', 'o', 'k', 'i',
4443 'e', 0x00, 0x00, 0x04,
4444 'n', 'a', 'm', 'e',
4445 0x05, 'v', 'a', 'l',
4446 'u', 'e',
4449 SpdyFramer framer(spdy_version_);
4450 TestSpdyVisitor visitor(spdy_version_);
4451 visitor.SimulateInFramer(kInput, sizeof(kInput));
4453 EXPECT_EQ(0, visitor.error_count_);
4454 EXPECT_EQ(1, visitor.headers_frame_count_);
4455 EXPECT_EQ(2, visitor.continuation_count_);
4456 EXPECT_EQ(1, visitor.fin_flag_count_);
4457 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4458 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4460 EXPECT_THAT(visitor.headers_,
4461 testing::ElementsAre(
4462 testing::Pair("cookie", "foo=bar; baz=bing; "),
4463 testing::Pair("name", "value")));
4466 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4467 if (spdy_version_ <= SPDY3) {
4468 return;
4471 const unsigned char kInput[] = {
4472 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4473 0x08, 0x00, 0x00, 0x00, // PADDED
4474 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4475 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4476 'c', 'o', 'o', 'k',
4477 'i', 'e', 0x07, 'f',
4478 'o', 'o', '=', 'b',
4479 'a', 'r', 0x00, 0x00,
4481 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4482 0x00, 0x00, 0x00, 0x00,
4483 0x01, 0x00, 0x06, 'c', // Stream 1
4484 'o', 'o', 'k', 'i',
4485 'e', 0x08, 'b', 'a',
4486 'z', '=', 'b', 'i',
4487 'n', 'g', 0x00, 0x06,
4488 'c',
4490 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4491 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4492 0x01, 'o', 'o', 'k', // Stream 1
4493 'i', 'e', 0x00, 0x00,
4494 0x04, 'n', 'a', 'm',
4495 'e', 0x05, 'v', 'a',
4496 'l', 'u', 'e',
4499 SpdyFramer framer(spdy_version_);
4500 TestSpdyVisitor visitor(spdy_version_);
4501 visitor.SimulateInFramer(kInput, sizeof(kInput));
4503 EXPECT_EQ(0, visitor.error_count_);
4504 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4505 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4506 EXPECT_EQ(2, visitor.continuation_count_);
4507 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4508 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4510 EXPECT_THAT(visitor.headers_,
4511 testing::ElementsAre(
4512 testing::Pair("cookie", "foo=bar; baz=bing; "),
4513 testing::Pair("name", "value")));
4516 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4517 if (spdy_version_ <= SPDY3) {
4518 return;
4521 const unsigned char kInput[] = {
4522 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4523 0x00, 0x00, 0x00, 0x01, // Stream 1
4524 0x00, 0x06, 0x63, 0x6f,
4525 0x6f, 0x6b, 0x69, 0x65,
4526 0x07, 0x66, 0x6f, 0x6f,
4527 0x3d, 0x62, 0x61, 0x72,
4529 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4530 0x00, 0x00, 0x00, 0x02, // Stream 2
4531 0x00, 0x06, 0x63, 0x6f,
4532 0x6f, 0x6b, 0x69, 0x65,
4533 0x08, 0x62, 0x61, 0x7a,
4534 0x3d, 0x62, 0x69, 0x6e,
4535 0x67, 0x00, 0x06, 0x63,
4538 SpdyFramer framer(spdy_version_);
4539 TestSpdyVisitor visitor(spdy_version_);
4540 framer.set_visitor(&visitor);
4541 visitor.SimulateInFramer(kInput, sizeof(kInput));
4543 EXPECT_EQ(1, visitor.error_count_);
4544 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4545 visitor.framer_.error_code())
4546 << SpdyFramer::ErrorCodeToString(framer.error_code());
4547 EXPECT_EQ(1, visitor.headers_frame_count_);
4548 EXPECT_EQ(0, visitor.continuation_count_);
4549 EXPECT_EQ(0u, visitor.header_buffer_length_);
4552 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4553 if (spdy_version_ <= SPDY3) {
4554 return;
4557 const unsigned char kInput[] = {
4558 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4559 0x00, 0x00, 0x00, 0x01, // Stream 1
4560 0x00, 0x06, 0x63, 0x6f,
4561 0x6f, 0x6b, 0x69, 0x65,
4562 0x07, 0x66, 0x6f, 0x6f,
4563 0x3d, 0x62, 0x61, 0x72,
4566 SpdyFramer framer(spdy_version_);
4567 TestSpdyVisitor visitor(spdy_version_);
4568 framer.set_visitor(&visitor);
4569 visitor.SimulateInFramer(kInput, sizeof(kInput));
4571 EXPECT_EQ(1, visitor.error_count_);
4572 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4573 visitor.framer_.error_code())
4574 << SpdyFramer::ErrorCodeToString(framer.error_code());
4575 EXPECT_EQ(0, visitor.continuation_count_);
4576 EXPECT_EQ(0u, visitor.header_buffer_length_);
4579 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4580 if (spdy_version_ <= SPDY3) {
4581 return;
4584 const unsigned char kInput[] = {
4585 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4586 0x00, 0x00, 0x00, 0x01, // Stream 1
4587 0x00, 0x06, 0x63, 0x6f,
4588 0x6f, 0x6b, 0x69, 0x65,
4589 0x07, 0x66, 0x6f, 0x6f,
4590 0x3d, 0x62, 0x61, 0x72,
4592 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4593 0x00, 0x00, 0x00, 0x04,
4594 0xde, 0xad, 0xbe, 0xef,
4597 SpdyFramer framer(spdy_version_);
4598 TestSpdyVisitor visitor(spdy_version_);
4599 framer.set_visitor(&visitor);
4600 visitor.SimulateInFramer(kInput, sizeof(kInput));
4602 EXPECT_EQ(1, visitor.error_count_);
4603 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4604 visitor.framer_.error_code())
4605 << SpdyFramer::ErrorCodeToString(framer.error_code());
4606 EXPECT_EQ(1, visitor.headers_frame_count_);
4607 EXPECT_EQ(0, visitor.continuation_count_);
4608 EXPECT_EQ(0u, visitor.header_buffer_length_);
4609 EXPECT_EQ(0, visitor.data_frame_count_);
4612 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4613 if (spdy_version_ <= SPDY3) {
4614 return;
4617 const unsigned char kInput[] = {
4618 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4619 0x00, 0x00, 0x00, 0x01, // Stream 1
4620 0x00, 0x06, 0x63, 0x6f,
4621 0x6f, 0x6b, 0x69, 0x65,
4622 0x07, 0x66, 0x6f, 0x6f,
4623 0x3d, 0x62, 0x61, 0x72,
4625 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4626 0x00, 0x00, 0x00, 0x01, // Stream 1
4627 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4628 0x6f, 0x6b, 0x69, 0x65,
4629 0x08, 0x62, 0x61, 0x7a,
4630 0x3d, 0x62, 0x69, 0x6e,
4631 0x67, 0x00, 0x06, 0x63,
4634 SpdyFramer framer(spdy_version_);
4635 TestSpdyVisitor visitor(spdy_version_);
4636 framer.set_visitor(&visitor);
4637 visitor.SimulateInFramer(kInput, sizeof(kInput));
4639 EXPECT_EQ(1, visitor.error_count_);
4640 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4641 visitor.framer_.error_code())
4642 << SpdyFramer::ErrorCodeToString(framer.error_code());
4643 EXPECT_EQ(1, visitor.headers_frame_count_);
4644 EXPECT_EQ(0, visitor.continuation_count_);
4645 EXPECT_EQ(0u, visitor.header_buffer_length_);
4646 EXPECT_EQ(0, visitor.data_frame_count_);
4649 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4650 if (spdy_version_ <= SPDY3) {
4651 return;
4653 const unsigned char kInput[] = {
4654 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4655 0x00, 0x00, 0x00, 0x01, // Stream 1
4656 0xde, 0xad, 0xbe, 0xef,
4657 0xde, 0xad, 0xbe, 0xef,
4658 0xde, 0xad, 0xbe, 0xef,
4661 TestSpdyVisitor visitor(spdy_version_);
4662 visitor.SimulateInFramer(kInput, sizeof(kInput));
4664 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4665 EXPECT_EQ(0, visitor.error_count_);
4666 EXPECT_EQ(12, visitor.data_bytes_);
4667 EXPECT_EQ(0, visitor.fin_frame_count_);
4668 EXPECT_EQ(0, visitor.fin_flag_count_);
4671 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4672 if (spdy_version_ <= SPDY3) {
4673 return;
4675 const unsigned char kInput[] = {
4676 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4677 0x00, 0x00, 0x00, 0x01, // Stream 1
4678 0x00, 0x06, 0x63, 0x6f,
4679 0x6f, 0x6b, 0x69, 0x65,
4680 0x07, 0x66, 0x6f, 0x6f,
4681 0x3d, 0x62, 0x61, 0x72,
4684 TestSpdyVisitor visitor(spdy_version_);
4685 visitor.SimulateInFramer(kInput, sizeof(kInput));
4687 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4688 EXPECT_EQ(0, visitor.error_count_);
4689 EXPECT_EQ(1, visitor.headers_frame_count_);
4690 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4692 EXPECT_THAT(visitor.headers_,
4693 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4696 TEST_P(SpdyFramerTest, ReadGarbage) {
4697 SpdyFramer framer(spdy_version_);
4698 unsigned char garbage_frame[256];
4699 memset(garbage_frame, ~0, sizeof(garbage_frame));
4700 TestSpdyVisitor visitor(spdy_version_);
4701 visitor.use_compression_ = false;
4702 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4703 EXPECT_EQ(1, visitor.error_count_);
4706 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4707 if (spdy_version_ <= SPDY3) {
4708 return;
4710 SpdyFramer framer(spdy_version_);
4712 // The unrecognized frame type should still have a valid length.
4713 const unsigned char unknown_frame[] = {
4714 0x00, 0x00, 0x08, 0xff, 0xff,
4715 0xff, 0xff, 0xff, 0xff,
4716 0xff, 0xff, 0xff, 0xff,
4717 0xff, 0xff, 0xff, 0xff,
4719 TestSpdyVisitor visitor(spdy_version_);
4721 // Simulate the case where the stream id validation checks out.
4722 visitor.on_unknown_frame_result_ = true;
4723 visitor.use_compression_ = false;
4724 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4725 EXPECT_EQ(0, visitor.error_count_);
4727 // Follow it up with a valid control frame to make sure we handle
4728 // subsequent frames correctly.
4729 SpdySettingsIR settings_ir;
4730 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4731 false, // persist
4732 false, // persisted
4733 10);
4734 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4735 visitor.SimulateInFramer(
4736 reinterpret_cast<unsigned char*>(control_frame->data()),
4737 control_frame->size());
4738 EXPECT_EQ(0, visitor.error_count_);
4739 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4740 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4743 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4744 if (!IsHttp2()) {
4745 return;
4747 SpdyFramer framer(spdy_version_);
4748 const unsigned char kFrameData[] = {
4749 0x00, 0x00, 0x08, 0xff, 0xff,
4750 0xff, 0xff, 0xff, 0xff,
4751 0xff, 0xff, 0xff, 0xff,
4752 0xff, 0xff, 0xff, 0xff,
4754 TestSpdyVisitor visitor(spdy_version_);
4755 visitor.use_compression_ = false;
4756 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4757 EXPECT_EQ(1, visitor.error_count_);
4760 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4761 if (IsHttp2()) {
4762 // Not valid for HTTP/2 since there is no version field.
4763 return;
4765 SpdyFramer framer(spdy_version_);
4766 const unsigned char kFrameData[] = {
4767 0x80, spdy_version_ch_, 0xff, 0xff,
4768 0xff, 0xff, 0xff, 0xff,
4770 TestSpdyVisitor visitor(spdy_version_);
4771 visitor.use_compression_ = false;
4772 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4773 EXPECT_EQ(1, visitor.error_count_);
4776 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4777 if (spdy_version_ <= SPDY3) {
4778 return;
4780 const unsigned char kInput[] = {
4781 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4782 0x00, 0x00, 0x00, 0x01, // Stream 1
4783 0xef, 0xef, 0xff, 0xff,
4784 0xff, 0xff, 0xff, 0xff,
4785 0xff, 0xff, 0xff, 0xff,
4786 0xff, 0xff, 0xff, 0xff,
4787 0xff, 0xff,
4790 TestSpdyVisitor visitor(spdy_version_);
4791 visitor.SimulateInFramer(kInput, arraysize(kInput));
4792 EXPECT_EQ(1, visitor.error_count_);
4795 TEST_P(SpdyFramerTest, SizesTest) {
4796 SpdyFramer framer(spdy_version_);
4797 if (IsHttp2()) {
4798 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4799 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4800 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4801 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4802 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4803 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4804 EXPECT_EQ(17u, framer.GetPingSize());
4805 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4806 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4807 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4808 EXPECT_EQ(9u, framer.GetBlockedSize());
4809 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4810 EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
4811 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4812 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4813 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4814 } else {
4815 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4816 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4817 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4818 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4819 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4820 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4821 EXPECT_EQ(12u, framer.GetPingSize());
4822 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4823 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4824 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4825 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4826 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4827 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4831 TEST_P(SpdyFramerTest, StateToStringTest) {
4832 EXPECT_STREQ("ERROR",
4833 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4834 EXPECT_STREQ("FRAME_COMPLETE",
4835 SpdyFramer::StateToString(SpdyFramer::SPDY_FRAME_COMPLETE));
4836 EXPECT_STREQ("READY_FOR_FRAME",
4837 SpdyFramer::StateToString(SpdyFramer::SPDY_READY_FOR_FRAME));
4838 EXPECT_STREQ("READING_COMMON_HEADER",
4839 SpdyFramer::StateToString(
4840 SpdyFramer::SPDY_READING_COMMON_HEADER));
4841 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4842 SpdyFramer::StateToString(
4843 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4844 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4845 SpdyFramer::StateToString(
4846 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4847 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4848 SpdyFramer::StateToString(
4849 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4850 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4851 SpdyFramer::StateToString(
4852 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4853 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4854 SpdyFramer::StateToString(
4855 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4856 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4857 SpdyFramer::StateToString(
4858 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4859 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4860 SpdyFramer::StateToString(
4861 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4862 EXPECT_STREQ("UNKNOWN_STATE",
4863 SpdyFramer::StateToString(
4864 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4867 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4868 EXPECT_STREQ("NO_ERROR",
4869 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4870 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4871 SpdyFramer::ErrorCodeToString(
4872 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4873 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4874 SpdyFramer::ErrorCodeToString(
4875 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4876 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4877 SpdyFramer::ErrorCodeToString(
4878 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4879 EXPECT_STREQ("UNSUPPORTED_VERSION",
4880 SpdyFramer::ErrorCodeToString(
4881 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4882 EXPECT_STREQ("DECOMPRESS_FAILURE",
4883 SpdyFramer::ErrorCodeToString(
4884 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4885 EXPECT_STREQ("COMPRESS_FAILURE",
4886 SpdyFramer::ErrorCodeToString(
4887 SpdyFramer::SPDY_COMPRESS_FAILURE));
4888 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4889 SpdyFramer::ErrorCodeToString(
4890 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4891 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4892 SpdyFramer::ErrorCodeToString(
4893 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4894 EXPECT_STREQ("UNKNOWN_ERROR",
4895 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4898 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4899 EXPECT_STREQ("INVALID",
4900 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4901 EXPECT_STREQ("PROTOCOL_ERROR",
4902 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4903 EXPECT_STREQ("INVALID_STREAM",
4904 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4905 EXPECT_STREQ("REFUSED_STREAM",
4906 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4907 EXPECT_STREQ("UNSUPPORTED_VERSION",
4908 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4909 EXPECT_STREQ("CANCEL",
4910 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4911 EXPECT_STREQ("INTERNAL_ERROR",
4912 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4913 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4914 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4915 EXPECT_STREQ("UNKNOWN_STATUS",
4916 SpdyFramer::StatusCodeToString(-1));
4919 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4920 EXPECT_STREQ("DATA",
4921 SpdyFramer::FrameTypeToString(DATA));
4922 EXPECT_STREQ("SYN_STREAM",
4923 SpdyFramer::FrameTypeToString(SYN_STREAM));
4924 EXPECT_STREQ("SYN_REPLY",
4925 SpdyFramer::FrameTypeToString(SYN_REPLY));
4926 EXPECT_STREQ("RST_STREAM",
4927 SpdyFramer::FrameTypeToString(RST_STREAM));
4928 EXPECT_STREQ("SETTINGS",
4929 SpdyFramer::FrameTypeToString(SETTINGS));
4930 EXPECT_STREQ("PING",
4931 SpdyFramer::FrameTypeToString(PING));
4932 EXPECT_STREQ("GOAWAY",
4933 SpdyFramer::FrameTypeToString(GOAWAY));
4934 EXPECT_STREQ("HEADERS",
4935 SpdyFramer::FrameTypeToString(HEADERS));
4936 EXPECT_STREQ("WINDOW_UPDATE",
4937 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4938 EXPECT_STREQ("PUSH_PROMISE",
4939 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4940 EXPECT_STREQ("CREDENTIAL",
4941 SpdyFramer::FrameTypeToString(CREDENTIAL));
4942 EXPECT_STREQ("CONTINUATION",
4943 SpdyFramer::FrameTypeToString(CONTINUATION));
4946 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4947 if (IsHttp2()) {
4948 // TODO(hkhalil): catch probable HTTP response in HTTP/2?
4949 return;
4952 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4953 SpdyFramer framer(spdy_version_);
4954 framer.set_visitor(&visitor);
4956 EXPECT_CALL(visitor, OnError(_));
4957 framer.ProcessInput("HTTP/1.1", 8);
4958 EXPECT_TRUE(framer.probable_http_response());
4959 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4960 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4961 << SpdyFramer::ErrorCodeToString(framer.error_code());
4964 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4965 SpdyFramer framer(spdy_version_);
4966 framer.set_visitor(&visitor);
4968 EXPECT_CALL(visitor, OnError(_));
4969 framer.ProcessInput("HTTP/1.0", 8);
4970 EXPECT_TRUE(framer.probable_http_response());
4971 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4972 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4973 << SpdyFramer::ErrorCodeToString(framer.error_code());
4977 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4978 if (spdy_version_ > SPDY3) {
4979 return;
4982 uint8 flags = 0;
4983 do {
4984 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4986 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4987 SpdyFramer framer(spdy_version_);
4988 framer.set_visitor(&visitor);
4990 SpdyDataIR data_ir(1, "hello");
4991 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4992 SetFrameFlags(frame.get(), flags, spdy_version_);
4994 if (flags & ~DATA_FLAG_FIN) {
4995 EXPECT_CALL(visitor, OnError(_));
4996 } else {
4997 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4998 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4999 if (flags & DATA_FLAG_FIN) {
5000 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5004 framer.ProcessInput(frame->data(), frame->size());
5005 if (flags & ~DATA_FLAG_FIN) {
5006 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5007 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
5008 framer.error_code())
5009 << SpdyFramer::ErrorCodeToString(framer.error_code());
5010 } else {
5011 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5012 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5013 << SpdyFramer::ErrorCodeToString(framer.error_code());
5015 } while (++flags != 0);
5018 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
5019 if (spdy_version_ <= SPDY3) {
5020 return;
5023 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
5024 DATA_FLAG_PADDED;
5026 uint8 flags = 0;
5027 do {
5028 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5030 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5031 SpdyFramer framer(spdy_version_);
5032 framer.set_visitor(&visitor);
5034 SpdyDataIR data_ir(1, "hello");
5035 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
5036 SetFrameFlags(frame.get(), flags, spdy_version_);
5038 if (flags & ~valid_data_flags) {
5039 EXPECT_CALL(visitor, OnError(_));
5040 } else {
5041 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
5042 if (flags & DATA_FLAG_PADDED) {
5043 // The first byte of payload is parsed as padding length.
5044 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
5045 // Expect Error since the frame ends prematurely.
5046 EXPECT_CALL(visitor, OnError(_));
5047 } else {
5048 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
5049 if (flags & DATA_FLAG_FIN) {
5050 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5055 framer.ProcessInput(frame->data(), frame->size());
5056 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
5057 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5058 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
5059 << SpdyFramer::ErrorCodeToString(framer.error_code());
5060 } else {
5061 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5062 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5063 << SpdyFramer::ErrorCodeToString(framer.error_code());
5065 } while (++flags != 0);
5068 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
5069 if (!IsSpdy2() && !IsSpdy3()) {
5070 // SYN_STREAM not supported in SPDY>3
5071 return;
5073 uint8 flags = 0;
5074 do {
5075 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5077 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5078 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5079 SpdyFramer framer(spdy_version_);
5080 framer.set_visitor(&visitor);
5081 framer.set_debug_visitor(&debug_visitor);
5083 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
5085 SpdySynStreamIR syn_stream(8);
5086 syn_stream.set_associated_to_stream_id(3);
5087 syn_stream.set_priority(1);
5088 syn_stream.SetHeader("foo", "bar");
5089 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5090 SetFrameFlags(frame.get(), flags, spdy_version_);
5092 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5093 EXPECT_CALL(visitor, OnError(_));
5094 } else {
5095 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
5096 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
5097 flags & CONTROL_FLAG_UNIDIRECTIONAL));
5098 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
5099 .WillRepeatedly(testing::Return(true));
5100 if (flags & DATA_FLAG_FIN) {
5101 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5102 } else {
5103 // Do not close the stream if we are expecting a CONTINUATION frame.
5104 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5108 framer.ProcessInput(frame->data(), frame->size());
5109 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5110 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5111 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5112 framer.error_code())
5113 << SpdyFramer::ErrorCodeToString(framer.error_code());
5114 } else {
5115 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5116 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5117 << SpdyFramer::ErrorCodeToString(framer.error_code());
5119 } while (++flags != 0);
5122 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
5123 if (!IsSpdy2() && !IsSpdy3()) {
5124 // SYN_REPLY not supported in SPDY>3
5125 return;
5127 uint8 flags = 0;
5128 do {
5129 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5131 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5132 SpdyFramer framer(spdy_version_);
5133 framer.set_visitor(&visitor);
5135 SpdySynReplyIR syn_reply(37);
5136 syn_reply.SetHeader("foo", "bar");
5137 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5138 SetFrameFlags(frame.get(), flags, spdy_version_);
5140 if (flags & ~CONTROL_FLAG_FIN) {
5141 EXPECT_CALL(visitor, OnError(_));
5142 } else {
5143 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5144 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5145 .WillRepeatedly(testing::Return(true));
5146 if (flags & DATA_FLAG_FIN) {
5147 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5151 framer.ProcessInput(frame->data(), frame->size());
5152 if (flags & ~CONTROL_FLAG_FIN) {
5153 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5154 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5155 framer.error_code())
5156 << SpdyFramer::ErrorCodeToString(framer.error_code());
5157 } else {
5158 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5159 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5160 << SpdyFramer::ErrorCodeToString(framer.error_code());
5162 } while (++flags != 0);
5165 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5166 uint8 flags = 0;
5167 do {
5168 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5170 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5171 SpdyFramer framer(spdy_version_);
5172 framer.set_visitor(&visitor);
5174 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5175 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5176 SetFrameFlags(frame.get(), flags, spdy_version_);
5178 if (flags != 0) {
5179 EXPECT_CALL(visitor, OnError(_));
5180 } else {
5181 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5184 framer.ProcessInput(frame->data(), frame->size());
5185 if (flags != 0) {
5186 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5187 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5188 framer.error_code())
5189 << SpdyFramer::ErrorCodeToString(framer.error_code());
5190 } else {
5191 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5192 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5193 << SpdyFramer::ErrorCodeToString(framer.error_code());
5195 } while (++flags != 0);
5198 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5199 if (spdy_version_ > SPDY3) { return; }
5200 uint8 flags = 0;
5201 do {
5202 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5204 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5205 SpdyFramer framer(spdy_version_);
5206 framer.set_visitor(&visitor);
5208 SpdySettingsIR settings_ir;
5209 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5210 false,
5211 false,
5212 54321);
5213 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5214 SetFrameFlags(frame.get(), flags, spdy_version_);
5216 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5217 EXPECT_CALL(visitor, OnError(_));
5218 } else {
5219 EXPECT_CALL(visitor, OnSettings(
5220 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5221 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5222 SETTINGS_FLAG_NONE, 54321));
5223 EXPECT_CALL(visitor, OnSettingsEnd());
5226 framer.ProcessInput(frame->data(), frame->size());
5227 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5228 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5229 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5230 framer.error_code())
5231 << SpdyFramer::ErrorCodeToString(framer.error_code());
5232 } else {
5233 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5234 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5235 << SpdyFramer::ErrorCodeToString(framer.error_code());
5237 } while (++flags != 0);
5240 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5241 if (spdy_version_ <= SPDY3) { return; }
5242 uint8 flags = 0;
5243 do {
5244 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5246 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5247 SpdyFramer framer(spdy_version_);
5248 framer.set_visitor(&visitor);
5250 SpdySettingsIR settings_ir;
5251 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5252 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5253 SetFrameFlags(frame.get(), flags, spdy_version_);
5255 if (flags != 0) {
5256 EXPECT_CALL(visitor, OnError(_));
5257 } else {
5258 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5259 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5260 EXPECT_CALL(visitor, OnSettingsEnd());
5263 framer.ProcessInput(frame->data(), frame->size());
5264 if (flags & ~SETTINGS_FLAG_ACK) {
5265 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5266 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5267 framer.error_code())
5268 << SpdyFramer::ErrorCodeToString(framer.error_code());
5269 } else if (flags & SETTINGS_FLAG_ACK) {
5270 // The frame is invalid because ACK frames should have no payload.
5271 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5272 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5273 framer.error_code())
5274 << SpdyFramer::ErrorCodeToString(framer.error_code());
5275 } else {
5276 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5277 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5278 << SpdyFramer::ErrorCodeToString(framer.error_code());
5280 } while (++flags != 0);
5283 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5284 uint8 flags = 0;
5285 do {
5286 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5288 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5289 SpdyFramer framer(spdy_version_);
5290 framer.set_visitor(&visitor);
5292 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5293 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5294 SetFrameFlags(frame.get(), flags, spdy_version_);
5296 if (flags != 0) {
5297 EXPECT_CALL(visitor, OnError(_));
5298 } else {
5299 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5302 framer.ProcessInput(frame->data(), frame->size());
5303 if (flags != 0) {
5304 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5305 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5306 framer.error_code())
5307 << SpdyFramer::ErrorCodeToString(framer.error_code());
5308 } else {
5309 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5310 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5311 << SpdyFramer::ErrorCodeToString(framer.error_code());
5313 } while (++flags != 0);
5316 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5317 uint8 flags = 0;
5318 do {
5319 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5321 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5322 SpdyFramer framer(spdy_version_);
5323 framer.set_visitor(&visitor);
5325 SpdyHeadersIR headers_ir(57);
5326 if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) {
5327 headers_ir.set_priority(3);
5328 headers_ir.set_has_priority(true);
5329 headers_ir.set_parent_stream_id(5);
5330 headers_ir.set_exclusive(true);
5332 headers_ir.SetHeader("foo", "bar");
5333 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5334 uint8 set_flags = flags;
5335 if (IsHttp2()) {
5336 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5337 // and implement framing.
5338 set_flags &= ~HEADERS_FLAG_PADDED;
5340 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5342 if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
5343 EXPECT_CALL(visitor, OnError(_));
5344 } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
5345 HEADERS_FLAG_END_HEADERS |
5346 HEADERS_FLAG_END_SEGMENT |
5347 HEADERS_FLAG_PADDED |
5348 HEADERS_FLAG_PRIORITY)) {
5349 EXPECT_CALL(visitor, OnError(_));
5350 } else {
5351 // Expected callback values
5352 SpdyStreamId stream_id = 57;
5353 bool has_priority = false;
5354 SpdyPriority priority = 0;
5355 SpdyStreamId parent_stream_id = 0;
5356 bool exclusive = false;
5357 bool fin = flags & CONTROL_FLAG_FIN;
5358 bool end = !IsHttp2() || (flags & HEADERS_FLAG_END_HEADERS);
5359 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5360 has_priority = true;
5361 priority = 3;
5362 parent_stream_id = 5;
5363 exclusive = true;
5365 EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority,
5366 parent_stream_id, exclusive, fin, end));
5367 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5368 .WillRepeatedly(testing::Return(true));
5369 if (flags & DATA_FLAG_FIN &&
5370 (!IsHttp2() || flags & HEADERS_FLAG_END_HEADERS)) {
5371 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5372 } else {
5373 // Do not close the stream if we are expecting a CONTINUATION frame.
5374 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5378 framer.ProcessInput(frame->data(), frame->size());
5379 if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
5380 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5381 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5382 framer.error_code())
5383 << SpdyFramer::ErrorCodeToString(framer.error_code());
5384 } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
5385 HEADERS_FLAG_END_HEADERS |
5386 HEADERS_FLAG_END_SEGMENT |
5387 HEADERS_FLAG_PADDED |
5388 HEADERS_FLAG_PRIORITY)) {
5389 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5390 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5391 framer.error_code())
5392 << SpdyFramer::ErrorCodeToString(framer.error_code());
5393 } else if (IsHttp2() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5394 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5395 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5396 << SpdyFramer::ErrorCodeToString(framer.error_code());
5397 } else {
5398 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5399 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5400 << SpdyFramer::ErrorCodeToString(framer.error_code());
5402 } while (++flags != 0);
5405 TEST_P(SpdyFramerTest, PingFrameFlags) {
5406 uint8 flags = 0;
5407 do {
5408 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5410 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5411 SpdyFramer framer(spdy_version_);
5412 framer.set_visitor(&visitor);
5414 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5415 SetFrameFlags(frame.get(), flags, spdy_version_);
5417 if (spdy_version_ > SPDY3 &&
5418 flags == PING_FLAG_ACK) {
5419 EXPECT_CALL(visitor, OnPing(42, true));
5420 } else if (flags == 0) {
5421 EXPECT_CALL(visitor, OnPing(42, false));
5422 } else {
5423 EXPECT_CALL(visitor, OnError(_));
5426 framer.ProcessInput(frame->data(), frame->size());
5427 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5428 flags == 0) {
5429 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5430 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5431 << SpdyFramer::ErrorCodeToString(framer.error_code());
5432 } else {
5433 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5434 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5435 framer.error_code())
5436 << SpdyFramer::ErrorCodeToString(framer.error_code());
5438 } while (++flags != 0);
5441 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5442 uint8 flags = 0;
5443 do {
5444 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5446 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5447 SpdyFramer framer(spdy_version_);
5448 framer.set_visitor(&visitor);
5450 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5451 SpdyWindowUpdateIR(4, 1024)));
5452 SetFrameFlags(frame.get(), flags, spdy_version_);
5454 if (flags != 0) {
5455 EXPECT_CALL(visitor, OnError(_));
5456 } else {
5457 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5460 framer.ProcessInput(frame->data(), frame->size());
5461 if (flags != 0) {
5462 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5463 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5464 framer.error_code())
5465 << SpdyFramer::ErrorCodeToString(framer.error_code());
5466 } else {
5467 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5468 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5469 << SpdyFramer::ErrorCodeToString(framer.error_code());
5471 } while (++flags != 0);
5474 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5475 if (spdy_version_ <= SPDY3) {
5476 return;
5479 uint8 flags = 0;
5480 do {
5481 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5483 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5484 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5485 SpdyFramer framer(spdy_version_);
5486 framer.set_visitor(&visitor);
5487 framer.set_debug_visitor(&debug_visitor);
5489 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5491 SpdyPushPromiseIR push_promise(42, 57);
5492 push_promise.SetHeader("foo", "bar");
5493 scoped_ptr<SpdySerializedFrame> frame(
5494 framer.SerializePushPromise(push_promise));
5495 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5496 // and implement framing.
5497 SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
5499 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5500 EXPECT_CALL(visitor, OnError(_));
5501 } else {
5502 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5503 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5504 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5505 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5506 .WillRepeatedly(testing::Return(true));
5509 framer.ProcessInput(frame->data(), frame->size());
5510 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5511 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5512 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5513 framer.error_code())
5514 << SpdyFramer::ErrorCodeToString(framer.error_code());
5515 } else {
5516 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5517 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5518 << SpdyFramer::ErrorCodeToString(framer.error_code());
5520 } while (++flags != 0);
5523 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5524 if (spdy_version_ <= SPDY3) {
5525 return;
5528 uint8 flags = 0;
5529 do {
5530 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5532 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5533 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5534 SpdyFramer framer(spdy_version_);
5535 framer.set_visitor(&visitor);
5536 framer.set_debug_visitor(&debug_visitor);
5538 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5539 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5540 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false, false, false));
5541 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5542 .WillRepeatedly(testing::Return(true));
5544 SpdyHeadersIR headers_ir(42);
5545 headers_ir.SetHeader("foo", "bar");
5546 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5547 SetFrameFlags(frame0.get(), 0, spdy_version_);
5549 SpdyContinuationIR continuation(42);
5550 continuation.SetHeader("foo", "bar");
5551 scoped_ptr<SpdySerializedFrame> frame(
5552 framer.SerializeContinuation(continuation));
5553 SetFrameFlags(frame.get(), flags, spdy_version_);
5555 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5556 EXPECT_CALL(visitor, OnError(_));
5557 } else {
5558 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5559 EXPECT_CALL(visitor, OnContinuation(42,
5560 flags & HEADERS_FLAG_END_HEADERS));
5561 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5562 .WillRepeatedly(testing::Return(true));
5565 framer.ProcessInput(frame0->data(), frame0->size());
5566 framer.ProcessInput(frame->data(), frame->size());
5567 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5568 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5569 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5570 framer.error_code())
5571 << SpdyFramer::ErrorCodeToString(framer.error_code());
5572 } else {
5573 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5574 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5575 << SpdyFramer::ErrorCodeToString(framer.error_code());
5577 } while (++flags != 0);
5580 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5582 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5584 TEST_P(SpdyFramerTest, EmptySynStream) {
5585 if (!IsSpdy2() && !IsSpdy3()) {
5586 // SYN_STREAM not supported in SPDY>3.
5587 return;
5589 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5590 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5591 SpdyFramer framer(spdy_version_);
5592 framer.set_visitor(&visitor);
5593 framer.set_debug_visitor(&debug_visitor);
5595 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5597 SpdySynStreamIR syn_stream(1);
5598 syn_stream.set_priority(1);
5599 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5600 // Adjust size to remove the header block.
5601 SetFrameLength(
5602 frame.get(),
5603 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5604 spdy_version_);
5606 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5607 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5608 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5610 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5611 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5612 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5613 << SpdyFramer::ErrorCodeToString(framer.error_code());
5616 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5617 const uint32 kId = 0x020304;
5618 const uint32 kFlags = 0x01;
5619 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5621 SettingsFlagsAndId id_and_flags =
5622 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5623 EXPECT_EQ(kId, id_and_flags.id());
5624 EXPECT_EQ(kFlags, id_and_flags.flags());
5625 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5628 // Test handling of a RST_STREAM with out-of-bounds status codes.
5629 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5630 const unsigned char kRstStreamStatusTooLow = 0x00;
5631 const unsigned char kRstStreamStatusTooHigh = 0xff;
5632 const unsigned char kV3RstStreamInvalid[] = {
5633 0x80, spdy_version_ch_, 0x00, 0x03,
5634 0x00, 0x00, 0x00, 0x08,
5635 0x00, 0x00, 0x00, 0x01,
5636 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5638 const unsigned char kH2RstStreamInvalid[] = {
5639 0x00, 0x00, 0x04, 0x03,
5640 0x00, 0x00, 0x00, 0x00,
5641 0x01, 0x00, 0x00, 0x00,
5642 kRstStreamStatusTooLow
5645 const unsigned char kV3RstStreamNumStatusCodes[] = {
5646 0x80, spdy_version_ch_, 0x00, 0x03,
5647 0x00, 0x00, 0x00, 0x08,
5648 0x00, 0x00, 0x00, 0x01,
5649 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5651 const unsigned char kH2RstStreamNumStatusCodes[] = {
5652 0x00, 0x00, 0x04, 0x03,
5653 0x00, 0x00, 0x00, 0x00,
5654 0x01, 0x00, 0x00, 0x00,
5655 kRstStreamStatusTooHigh
5658 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5659 SpdyFramer framer(spdy_version_);
5660 framer.set_visitor(&visitor);
5662 if (IsHttp2()) {
5663 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5664 framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
5665 arraysize(kH2RstStreamInvalid));
5666 } else {
5667 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5668 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5669 arraysize(kV3RstStreamInvalid));
5671 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5672 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5673 << SpdyFramer::ErrorCodeToString(framer.error_code());
5676 framer.Reset();
5678 if (IsHttp2()) {
5679 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5680 framer.ProcessInput(
5681 reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
5682 arraysize(kH2RstStreamNumStatusCodes));
5683 } else {
5684 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5685 framer.ProcessInput(
5686 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5687 arraysize(kV3RstStreamNumStatusCodes));
5689 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5690 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5691 << SpdyFramer::ErrorCodeToString(framer.error_code());
5694 // Test handling of GOAWAY frames with out-of-bounds status code.
5695 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5696 if (spdy_version_ <= SPDY2) {
5697 return;
5699 SpdyFramer framer(spdy_version_);
5701 const unsigned char kV3FrameData[] = {
5702 0x80, spdy_version_ch_, 0x00, 0x07,
5703 0x00, 0x00, 0x00, 0x08,
5704 0x00, 0x00, 0x00, 0x01, // Stream Id
5705 0xff, 0xff, 0xff, 0xff, // Status
5707 const unsigned char kH2FrameData[] = {
5708 0x00, 0x00, 0x0a, 0x07,
5709 0x00, 0x00, 0x00, 0x00,
5710 0x00, 0x00, 0x00, 0x00, // Stream id
5711 0x01, 0xff, 0xff, 0xff, // Status
5712 0xff, 0x47, 0x41, // Opaque Description
5714 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5715 framer.set_visitor(&visitor);
5717 if (IsSpdy3()) {
5718 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5719 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5720 arraysize(kV3FrameData));
5721 } else {
5722 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5723 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
5724 arraysize(kH2FrameData));
5726 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5727 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5728 << SpdyFramer::ErrorCodeToString(framer.error_code());
5731 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5732 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5733 const unsigned char kV2FrameData[] = {
5734 0x80, spdy_version_ch_, 0x00, 0x07,
5735 0x00, 0x00, 0x00, 0x04,
5736 0xff, 0xff, 0xff, 0xff,
5738 const unsigned char kV3FrameData[] = {
5739 0x80, spdy_version_ch_, 0x00, 0x07,
5740 0x00, 0x00, 0x00, 0x08,
5741 0xff, 0xff, 0xff, 0xff,
5742 0x00, 0x00, 0x00, 0x00,
5744 const unsigned char kH2FrameData[] = {
5745 0x00, 0x00, 0x08, 0x07,
5746 0x00, 0x00, 0x00, 0x00,
5747 0x00, 0xff, 0xff, 0xff,
5748 0xff, 0x00, 0x00, 0x00,
5749 0x00,
5752 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5753 SpdyFramer framer(spdy_version_);
5754 framer.set_visitor(&visitor);
5756 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5757 if (IsSpdy2()) {
5758 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5759 arraysize(kV2FrameData));
5760 } else if (IsSpdy3()) {
5761 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5762 arraysize(kV3FrameData));
5763 } else {
5764 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
5765 arraysize(kH2FrameData));
5767 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5768 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5769 << SpdyFramer::ErrorCodeToString(framer.error_code());
5772 TEST_P(SpdyFramerTest, OnBlocked) {
5773 if (spdy_version_ <= SPDY3) {
5774 return;
5777 const SpdyStreamId kStreamId = 0;
5779 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5780 SpdyFramer framer(spdy_version_);
5781 framer.set_visitor(&visitor);
5783 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5785 SpdyBlockedIR blocked_ir(0);
5786 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5787 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5789 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5790 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5791 << SpdyFramer::ErrorCodeToString(framer.error_code());
5794 TEST_P(SpdyFramerTest, OnAltSvc) {
5795 if (spdy_version_ <= SPDY3) {
5796 return;
5799 const SpdyStreamId kStreamId = 1;
5801 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5802 SpdyFramer framer(spdy_version_);
5803 framer.set_visitor(&visitor);
5805 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5806 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5807 42, 0.2);
5808 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5809 altsvc_vector.push_back(altsvc1);
5810 altsvc_vector.push_back(altsvc2);
5811 EXPECT_CALL(visitor,
5812 OnAltSvc(kStreamId, StringPiece("o_r|g!n"), altsvc_vector));
5814 SpdyAltSvcIR altsvc_ir(1);
5815 altsvc_ir.set_origin("o_r|g!n");
5816 altsvc_ir.add_altsvc(altsvc1);
5817 altsvc_ir.add_altsvc(altsvc2);
5818 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5819 framer.ProcessInput(frame->data(), frame->size());
5821 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5822 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5823 << SpdyFramer::ErrorCodeToString(framer.error_code());
5826 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5827 if (spdy_version_ <= SPDY3) {
5828 return;
5831 const SpdyStreamId kStreamId = 1;
5833 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5834 SpdyFramer framer(spdy_version_);
5835 framer.set_visitor(&visitor);
5837 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5838 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5839 42, 0.2);
5840 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5841 altsvc_vector.push_back(altsvc1);
5842 altsvc_vector.push_back(altsvc2);
5843 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece(""), altsvc_vector));
5845 SpdyAltSvcIR altsvc_ir(1);
5846 altsvc_ir.add_altsvc(altsvc1);
5847 altsvc_ir.add_altsvc(altsvc2);
5848 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5849 framer.ProcessInput(frame->data(), frame->size());
5851 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5852 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5853 << SpdyFramer::ErrorCodeToString(framer.error_code());
5856 TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
5857 if (spdy_version_ <= SPDY3) {
5858 return;
5861 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5862 SpdyFramer framer(spdy_version_);
5863 framer.set_visitor(&visitor);
5865 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
5867 SpdyAltSvcIR altsvc_ir(1);
5868 altsvc_ir.set_origin("o1");
5869 altsvc_ir.add_altsvc(
5870 SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0));
5871 altsvc_ir.add_altsvc(
5872 SpdyAltSvcWireFormat::AlternativeService("", "h1", 443, 10, 1.0));
5873 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5874 framer.ProcessInput(frame->data(), frame->size());
5876 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5877 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
5878 << SpdyFramer::ErrorCodeToString(framer.error_code());
5881 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5882 if (spdy_version_ <= SPDY3) {
5883 return;
5886 const SpdyStreamId kStreamId = 1;
5888 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5889 SpdyFramer framer(spdy_version_);
5890 framer.set_visitor(&visitor);
5892 SpdyAltSvcWireFormat::AlternativeService altsvc("pid", "h1", 443, 10, 1.0);
5893 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5894 altsvc_vector.push_back(altsvc);
5895 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece("o1"), altsvc_vector));
5897 SpdyAltSvcIR altsvc_ir(1);
5898 altsvc_ir.set_origin("o1");
5899 altsvc_ir.add_altsvc(altsvc);
5900 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5901 framer.ProcessInput(frame->data(), frame->size());
5903 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5904 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5905 << SpdyFramer::ErrorCodeToString(framer.error_code());
5908 // Tests handling of ALTSVC frames delivered in small chunks.
5909 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5910 if (spdy_version_ <= SPDY3) {
5911 return;
5914 SpdyFramer framer(spdy_version_);
5915 SpdyAltSvcIR altsvc_ir(1);
5916 SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0);
5917 SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123,
5918 42, 0.2);
5919 altsvc_ir.add_altsvc(altsvc1);
5920 altsvc_ir.add_altsvc(altsvc2);
5922 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5923 TestSpdyVisitor visitor(spdy_version_);
5924 visitor.use_compression_ = false;
5926 // Read data in small chunks.
5927 size_t framed_data = 0;
5928 size_t unframed_data = control_frame->size();
5929 size_t kReadChunkSize = 5; // Read five bytes at a time.
5930 while (unframed_data > 0) {
5931 size_t to_read = std::min(kReadChunkSize, unframed_data);
5932 visitor.SimulateInFramer(
5933 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5934 to_read);
5935 unframed_data -= to_read;
5936 framed_data += to_read;
5938 EXPECT_EQ(0, visitor.error_count_);
5939 EXPECT_EQ(1, visitor.altsvc_count_);
5940 ASSERT_EQ(2u, visitor.test_altsvc_ir_.altsvc_vector().size());
5941 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[0] == altsvc1);
5942 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[1] == altsvc2);
5945 // Tests handling of PRIORITY frames.
5946 TEST_P(SpdyFramerTest, ReadPriority) {
5947 if (spdy_version_ <= SPDY3) {
5948 return;
5950 SpdyFramer framer(spdy_version_);
5951 SpdyPriorityIR priority(3, 1, 255, false);
5952 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5953 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5954 framer.set_visitor(&visitor);
5955 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5956 framer.ProcessInput(frame->data(), frame->size());
5958 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
5959 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5960 << SpdyFramer::ErrorCodeToString(framer.error_code());
5961 // TODO(mlavan): once we actually maintain a priority tree,
5962 // check that state is adjusted correctly.
5965 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5966 if (spdy_version_ <= SPDY3) {
5967 return;
5969 SpdyFramer framer(spdy_version_);
5971 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5972 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5973 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5974 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5975 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5976 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5977 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5978 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5980 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5981 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5982 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5983 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5984 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5985 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5986 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5987 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5988 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5989 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5990 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5991 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5992 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5993 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5994 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5997 // Tests handling of PRIORITY frame with incorrect size.
5998 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5999 if (spdy_version_ <= SPDY3) {
6000 return;
6003 // PRIORITY frame of size 4, which isn't correct.
6004 const unsigned char kFrameData[] = {
6005 0x00, 0x00, 0x04, 0x02, 0x00,
6006 0x00, 0x00, 0x00, 0x03,
6007 0x00, 0x00, 0x00, 0x01,
6010 TestSpdyVisitor visitor(spdy_version_);
6011 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
6013 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
6014 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
6015 visitor.framer_.error_code())
6016 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
6019 // Test that SpdyFramer processes, by default, all passed input in one call
6020 // to ProcessInput (i.e. will not be calling set_process_single_input_frame()).
6021 TEST_P(SpdyFramerTest, ProcessAllInput) {
6022 SpdyFramer framer(spdy_version_);
6023 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
6024 framer.set_visitor(visitor.get());
6026 // Create two input frames.
6027 SpdyHeadersIR headers(1);
6028 headers.set_priority(1);
6029 headers.SetHeader("alpha", "beta");
6030 headers.SetHeader("gamma", "charlie");
6031 headers.SetHeader("cookie", "key1=value1; key2=value2");
6032 scoped_ptr<SpdyFrame> headers_frame(framer.SerializeHeaders(headers));
6034 const char four_score[] = "Four score and seven years ago";
6035 SpdyDataIR four_score_ir(1, four_score);
6036 scoped_ptr<SpdyFrame> four_score_frame(framer.SerializeData(four_score_ir));
6038 // Put them in a single buffer (new variables here to make it easy to
6039 // change the order and type of frames).
6040 SpdyFrame* frame1 = headers_frame.get();
6041 SpdyFrame* frame2 = four_score_frame.get();
6043 const size_t frame1_size = frame1->size();
6044 const size_t frame2_size = frame2->size();
6046 LOG(INFO) << "frame1_size = " << frame1_size;
6047 LOG(INFO) << "frame2_size = " << frame2_size;
6049 string input_buffer;
6050 input_buffer.append(frame1->data(), frame1_size);
6051 input_buffer.append(frame2->data(), frame2_size);
6053 const char* buf = input_buffer.data();
6054 const size_t buf_size = input_buffer.size();
6056 LOG(INFO) << "buf_size = " << buf_size;
6058 size_t processed = framer.ProcessInput(buf, buf_size);
6059 EXPECT_EQ(buf_size, processed);
6060 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
6061 EXPECT_EQ(1, visitor->headers_frame_count_);
6062 EXPECT_EQ(1, visitor->data_frame_count_);
6063 EXPECT_EQ(strlen(four_score), static_cast<unsigned>(visitor->data_bytes_));
6066 // Test that SpdyFramer stops after processing a full frame if
6067 // process_single_input_frame is set. Input to ProcessInput has two frames, but
6068 // only processes the first when we give it the first frame split at any point,
6069 // or give it more than one frame in the input buffer.
6070 TEST_P(SpdyFramerTest, ProcessAtMostOneFrame) {
6071 SpdyFramer framer(spdy_version_);
6072 framer.set_process_single_input_frame(true);
6073 scoped_ptr<TestSpdyVisitor> visitor;
6075 // Create two input frames.
6076 const char four_score[] = "Four score and ...";
6077 SpdyDataIR four_score_ir(1, four_score);
6078 scoped_ptr<SpdyFrame> four_score_frame(framer.SerializeData(four_score_ir));
6080 SpdyHeadersIR headers(2);
6081 headers.SetHeader("alpha", "beta");
6082 headers.SetHeader("gamma", "charlie");
6083 headers.SetHeader("cookie", "key1=value1; key2=value2");
6084 scoped_ptr<SpdyFrame> headers_frame(framer.SerializeHeaders(headers));
6086 // Put them in a single buffer (new variables here to make it easy to
6087 // change the order and type of frames).
6088 SpdyFrame* frame1 = four_score_frame.get();
6089 SpdyFrame* frame2 = headers_frame.get();
6091 const size_t frame1_size = frame1->size();
6092 const size_t frame2_size = frame2->size();
6094 LOG(INFO) << "frame1_size = " << frame1_size;
6095 LOG(INFO) << "frame2_size = " << frame2_size;
6097 string input_buffer;
6098 input_buffer.append(frame1->data(), frame1_size);
6099 input_buffer.append(frame2->data(), frame2_size);
6101 const char* buf = input_buffer.data();
6102 const size_t buf_size = input_buffer.size();
6104 LOG(INFO) << "buf_size = " << buf_size;
6106 for (size_t first_size = 0; first_size <= buf_size; ++first_size) {
6107 LOG(INFO) << "first_size = " << first_size;
6108 visitor.reset(new TestSpdyVisitor(spdy_version_));
6109 framer.set_visitor(visitor.get());
6111 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
6113 size_t processed_first = framer.ProcessInput(buf, first_size);
6114 if (first_size < frame1_size) {
6115 EXPECT_EQ(first_size, processed_first);
6117 if (first_size == 0) {
6118 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
6119 } else {
6120 EXPECT_NE(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
6123 const char* rest = buf + processed_first;
6124 const size_t remaining = buf_size - processed_first;
6125 LOG(INFO) << "remaining = " << remaining;
6127 size_t processed_second = framer.ProcessInput(rest, remaining);
6129 // Redundant tests just to make it easier to think about.
6130 EXPECT_EQ(frame1_size - processed_first, processed_second);
6131 size_t processed_total = processed_first + processed_second;
6132 EXPECT_EQ(frame1_size, processed_total);
6133 } else {
6134 EXPECT_EQ(frame1_size, processed_first);
6137 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
6139 // At this point should have processed the entirety of the first frame,
6140 // and none of the second frame.
6142 EXPECT_EQ(1, visitor->data_frame_count_);
6143 EXPECT_EQ(strlen(four_score), static_cast<unsigned>(visitor->data_bytes_));
6144 EXPECT_EQ(0, visitor->headers_frame_count_);
6148 } // namespace test
6150 } // namespace net