Move StartsWith[ASCII] to base namespace.
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob103af39d8dee3d61a6d1e9010da704819f26cb4e
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <algorithm>
6 #include <iostream>
7 #include <limits>
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/spdy/hpack_output_stream.h"
12 #include "net/spdy/mock_spdy_framer_visitor.h"
13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_framer.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/spdy/spdy_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/platform_test.h"
21 using std::string;
22 using testing::_;
24 namespace net {
26 namespace test {
28 static const size_t kMaxDecompressedSize = 1024;
30 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
31 public:
32 MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
33 SpdyFrameType type,
34 size_t payload_len,
35 size_t frame_len));
37 MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
38 SpdyFrameType type,
39 size_t frame_len));
42 class SpdyFramerTestUtil {
43 public:
44 // Decompress a single frame using the decompression context held by
45 // the SpdyFramer. The implemention is meant for use only in tests
46 // and will CHECK fail if the input is anything other than a single,
47 // well-formed compressed frame.
49 // Returns a new decompressed SpdyFrame.
50 template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
51 SpdyFramer* framer, const SpdyFrameType& frame) {
52 DecompressionVisitor visitor(framer->protocol_version());
53 framer->set_visitor(&visitor);
54 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
55 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
56 framer->set_visitor(NULL);
58 char* buffer = visitor.ReleaseBuffer();
59 CHECK(buffer != NULL);
60 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
61 SetFrameLength(decompressed_frame,
62 visitor.size() - framer->GetControlFrameHeaderSize(),
63 framer->protocol_version());
64 return decompressed_frame;
67 class DecompressionVisitor : public SpdyFramerVisitorInterface {
68 public:
69 explicit DecompressionVisitor(SpdyMajorVersion version)
70 : version_(version), size_(0), finished_(false) {}
72 void ResetBuffer() {
73 CHECK(buffer_.get() == NULL);
74 CHECK_EQ(0u, size_);
75 CHECK(!finished_);
76 buffer_.reset(new char[kMaxDecompressedSize]);
79 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
80 void OnDataFrameHeader(SpdyStreamId stream_id,
81 size_t length,
82 bool fin) override {
83 LOG(FATAL) << "Unexpected data frame header";
85 void OnStreamFrameData(SpdyStreamId stream_id,
86 const char* data,
87 size_t len,
88 bool fin) override {
89 LOG(FATAL);
92 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
93 LOG(FATAL);
96 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
97 const char* header_data,
98 size_t len) override {
99 CHECK(buffer_.get() != NULL);
100 CHECK_GE(kMaxDecompressedSize, size_ + len);
101 CHECK(!finished_);
102 if (len != 0) {
103 memcpy(buffer_.get() + size_, header_data, len);
104 size_ += len;
105 } else {
106 // Done.
107 finished_ = true;
109 return true;
112 void OnSynStream(SpdyStreamId stream_id,
113 SpdyStreamId associated_stream_id,
114 SpdyPriority priority,
115 bool fin,
116 bool unidirectional) override {
117 SpdyFramer framer(version_);
118 framer.set_enable_compression(false);
119 SpdySynStreamIR syn_stream(stream_id);
120 syn_stream.set_associated_to_stream_id(associated_stream_id);
121 syn_stream.set_priority(priority);
122 syn_stream.set_fin(fin);
123 syn_stream.set_unidirectional(unidirectional);
124 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
125 ResetBuffer();
126 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
127 size_ += framer.GetSynStreamMinimumSize();
130 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
131 SpdyFramer framer(version_);
132 framer.set_enable_compression(false);
133 SpdyHeadersIR headers(stream_id);
134 headers.set_fin(fin);
135 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
136 ResetBuffer();
137 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
138 size_ += framer.GetSynStreamMinimumSize();
141 void OnRstStream(SpdyStreamId stream_id,
142 SpdyRstStreamStatus status) override {
143 LOG(FATAL);
145 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
146 LOG(FATAL);
148 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
149 void OnSettingsEnd() override { LOG(FATAL); }
150 void OnGoAway(SpdyStreamId last_accepted_stream_id,
151 SpdyGoAwayStatus status) override {
152 LOG(FATAL);
155 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
156 SpdyPriority priority, bool fin, bool end) override {
157 SpdyFramer framer(version_);
158 framer.set_enable_compression(false);
159 SpdyHeadersIR headers(stream_id);
160 headers.set_has_priority(has_priority);
161 if (headers.has_priority()) {
162 headers.set_priority(priority);
164 headers.set_fin(fin);
165 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
166 ResetBuffer();
167 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
168 size_ += framer.GetHeadersMinimumSize();
171 virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
172 LOG(FATAL);
175 void OnPushPromise(SpdyStreamId stream_id,
176 SpdyStreamId promised_stream_id,
177 bool end) override {
178 SpdyFramer framer(version_);
179 framer.set_enable_compression(false);
180 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
181 scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
182 ResetBuffer();
183 memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
184 size_ += framer.GetPushPromiseMinimumSize();
187 void OnContinuation(SpdyStreamId stream_id, bool end) override {
188 LOG(FATAL);
191 void OnPriority(SpdyStreamId stream_id,
192 SpdyStreamId parent_stream_id,
193 uint8 weight,
194 bool exclusive) override {
195 // Do nothing.
198 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
199 LOG(FATAL);
200 return false;
203 char* ReleaseBuffer() {
204 CHECK(finished_);
205 return buffer_.release();
208 void OnWindowUpdate(SpdyStreamId stream_id,
209 uint32 delta_window_size) override {
210 LOG(FATAL);
213 size_t size() const {
214 CHECK(finished_);
215 return size_;
218 private:
219 SpdyMajorVersion version_;
220 scoped_ptr<char[]> buffer_;
221 size_t size_;
222 bool finished_;
224 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
227 private:
228 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
231 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
232 public SpdyFramerDebugVisitorInterface {
233 public:
234 // This is larger than our max frame size because header blocks that
235 // are too long can spill over into CONTINUATION frames.
236 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
238 explicit TestSpdyVisitor(SpdyMajorVersion version)
239 : framer_(version),
240 use_compression_(false),
241 error_count_(0),
242 syn_frame_count_(0),
243 syn_reply_frame_count_(0),
244 headers_frame_count_(0),
245 push_promise_frame_count_(0),
246 goaway_count_(0),
247 setting_count_(0),
248 settings_ack_sent_(0),
249 settings_ack_received_(0),
250 continuation_count_(0),
251 altsvc_count_(0),
252 priority_count_(0),
253 test_altsvc_ir_(0),
254 on_unknown_frame_result_(false),
255 last_window_update_stream_(0),
256 last_window_update_delta_(0),
257 last_push_promise_stream_(0),
258 last_push_promise_promised_stream_(0),
259 data_bytes_(0),
260 fin_frame_count_(0),
261 fin_opaque_data_(),
262 fin_flag_count_(0),
263 zero_length_data_frame_count_(0),
264 control_frame_header_data_count_(0),
265 zero_length_control_frame_header_data_count_(0),
266 data_frame_count_(0),
267 last_payload_len_(0),
268 last_frame_len_(0),
269 header_buffer_(new char[kDefaultHeaderBufferSize]),
270 header_buffer_length_(0),
271 header_buffer_size_(kDefaultHeaderBufferSize),
272 header_stream_id_(static_cast<SpdyStreamId>(-1)),
273 header_control_type_(DATA),
274 header_buffer_valid_(false) {}
276 void OnError(SpdyFramer* f) override {
277 LOG(INFO) << "SpdyFramer Error: "
278 << SpdyFramer::ErrorCodeToString(f->error_code());
279 ++error_count_;
282 void OnDataFrameHeader(SpdyStreamId stream_id,
283 size_t length,
284 bool fin) override {
285 ++data_frame_count_;
286 header_stream_id_ = stream_id;
289 void OnStreamFrameData(SpdyStreamId stream_id,
290 const char* data,
291 size_t len,
292 bool fin) override {
293 EXPECT_EQ(header_stream_id_, stream_id);
294 if (len == 0)
295 ++zero_length_data_frame_count_;
297 data_bytes_ += len;
298 LOG(INFO) << "OnStreamFrameData(" << stream_id << ", \"";
299 if (len > 0) {
300 for (size_t i = 0 ; i < len; ++i) {
301 LOG(INFO) << std::hex << (0xFF & static_cast<unsigned int>(data[i]))
302 << std::dec;
305 LOG(INFO) << "\", " << len << ")\n";
308 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
309 EXPECT_EQ(header_stream_id_, stream_id);
310 data_bytes_ += len;
311 LOG(INFO) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
314 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
315 const char* header_data,
316 size_t len) override {
317 ++control_frame_header_data_count_;
318 CHECK_EQ(header_stream_id_, stream_id);
319 if (len == 0) {
320 ++zero_length_control_frame_header_data_count_;
321 // Indicates end-of-header-block.
322 headers_.clear();
323 CHECK(header_buffer_valid_);
324 size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
325 header_buffer_.get(), header_buffer_length_, &headers_);
326 LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
327 << "Check failed: header_buffer_length_ == parsed_length "
328 << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
329 return true;
331 const size_t available = header_buffer_size_ - header_buffer_length_;
332 if (len > available) {
333 header_buffer_valid_ = false;
334 return false;
336 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
337 header_buffer_length_ += len;
338 return true;
341 void OnSynStream(SpdyStreamId stream_id,
342 SpdyStreamId associated_stream_id,
343 SpdyPriority priority,
344 bool fin,
345 bool unidirectional) override {
346 ++syn_frame_count_;
347 if (framer_.protocol_version() > SPDY3) {
348 InitHeaderStreaming(HEADERS, stream_id);
349 } else {
350 InitHeaderStreaming(SYN_STREAM, stream_id);
352 if (fin) {
353 ++fin_flag_count_;
357 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
358 ++syn_reply_frame_count_;
359 if (framer_.protocol_version() > SPDY3) {
360 InitHeaderStreaming(HEADERS, stream_id);
361 } else {
362 InitHeaderStreaming(SYN_REPLY, stream_id);
364 if (fin) {
365 ++fin_flag_count_;
369 void OnRstStream(SpdyStreamId stream_id,
370 SpdyRstStreamStatus status) override {
371 ++fin_frame_count_;
374 bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
375 if ((rst_stream_data != NULL) && (len > 0)) {
376 fin_opaque_data_ += string(rst_stream_data, len);
378 return true;
381 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
382 ++setting_count_;
385 void OnSettingsAck() override {
386 DCHECK_LT(SPDY3, framer_.protocol_version());
387 ++settings_ack_received_;
390 void OnSettingsEnd() override {
391 if (framer_.protocol_version() <= SPDY3) { return; }
392 ++settings_ack_sent_;
395 void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
397 void OnGoAway(SpdyStreamId last_accepted_stream_id,
398 SpdyGoAwayStatus status) override {
399 ++goaway_count_;
402 void OnHeaders(SpdyStreamId stream_id, bool has_priority,
403 SpdyPriority priority, bool fin, bool end) override {
404 ++headers_frame_count_;
405 InitHeaderStreaming(HEADERS, stream_id);
406 if (fin) {
407 ++fin_flag_count_;
411 void OnWindowUpdate(SpdyStreamId stream_id,
412 uint32 delta_window_size) override {
413 last_window_update_stream_ = stream_id;
414 last_window_update_delta_ = delta_window_size;
417 void OnPushPromise(SpdyStreamId stream_id,
418 SpdyStreamId promised_stream_id,
419 bool end) override {
420 ++push_promise_frame_count_;
421 InitHeaderStreaming(PUSH_PROMISE, stream_id);
422 last_push_promise_stream_ = stream_id;
423 last_push_promise_promised_stream_ = promised_stream_id;
426 void OnContinuation(SpdyStreamId stream_id, bool end) override {
427 ++continuation_count_;
430 void OnAltSvc(
431 SpdyStreamId stream_id,
432 StringPiece origin,
433 const SpdyAltSvcWireFormat::AlternativeService& altsvc) override {
434 test_altsvc_ir_.set_stream_id(stream_id);
435 if (origin.length() > 0) {
436 test_altsvc_ir_.set_origin(origin.as_string());
438 test_altsvc_ir_.set_protocol_id(altsvc.protocol_id);
439 test_altsvc_ir_.set_host(altsvc.host);
440 test_altsvc_ir_.set_port(altsvc.port);
441 test_altsvc_ir_.set_max_age(altsvc.max_age);
442 test_altsvc_ir_.set_p(altsvc.p);
443 ++altsvc_count_;
446 void OnPriority(SpdyStreamId stream_id,
447 SpdyStreamId parent_stream_id,
448 uint8 weight,
449 bool exclusive) override {
450 ++priority_count_;
453 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
454 DLOG(INFO) << "Unknown frame type " << frame_type;
455 return on_unknown_frame_result_;
458 void OnSendCompressedFrame(SpdyStreamId stream_id,
459 SpdyFrameType type,
460 size_t payload_len,
461 size_t frame_len) override {
462 last_payload_len_ = payload_len;
463 last_frame_len_ = frame_len;
466 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
467 SpdyFrameType type,
468 size_t frame_len) override {
469 last_frame_len_ = frame_len;
472 // Convenience function which runs a framer simulation with particular input.
473 void SimulateInFramer(const unsigned char* input, size_t size) {
474 framer_.set_enable_compression(use_compression_);
475 framer_.set_visitor(this);
476 size_t input_remaining = size;
477 const char* input_ptr = reinterpret_cast<const char*>(input);
478 while (input_remaining > 0 &&
479 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
480 // To make the tests more interesting, we feed random (amd small) chunks
481 // into the framer. This simulates getting strange-sized reads from
482 // the socket.
483 const size_t kMaxReadSize = 32;
484 size_t bytes_read =
485 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
486 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
487 input_remaining -= bytes_processed;
488 input_ptr += bytes_processed;
492 void InitHeaderStreaming(SpdyFrameType header_control_type,
493 SpdyStreamId stream_id) {
494 if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
495 SpdyConstants::SerializeFrameType(framer_.protocol_version(),
496 header_control_type))) {
497 DLOG(FATAL) << "Attempted to init header streaming with "
498 << "invalid control frame type: "
499 << header_control_type;
501 memset(header_buffer_.get(), 0, header_buffer_size_);
502 header_buffer_length_ = 0;
503 header_stream_id_ = stream_id;
504 header_control_type_ = header_control_type;
505 header_buffer_valid_ = true;
506 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
509 // Override the default buffer size (16K). Call before using the framer!
510 void set_header_buffer_size(size_t header_buffer_size) {
511 header_buffer_size_ = header_buffer_size;
512 header_buffer_.reset(new char[header_buffer_size]);
515 // Largest control frame that the SPDY implementation sends, including the
516 // size of the header.
517 static size_t sent_control_frame_max_size() {
518 return SpdyFramer::kMaxControlFrameSize;
521 static size_t header_data_chunk_max_size() {
522 return SpdyFramer::kHeaderDataChunkMaxSize;
525 SpdyFramer framer_;
526 bool use_compression_;
528 // Counters from the visitor callbacks.
529 int error_count_;
530 int syn_frame_count_;
531 int syn_reply_frame_count_;
532 int headers_frame_count_;
533 int push_promise_frame_count_;
534 int goaway_count_;
535 int setting_count_;
536 int settings_ack_sent_;
537 int settings_ack_received_;
538 int continuation_count_;
539 int altsvc_count_;
540 int priority_count_;
541 SpdyAltSvcIR test_altsvc_ir_;
542 bool on_unknown_frame_result_;
543 SpdyStreamId last_window_update_stream_;
544 uint32 last_window_update_delta_;
545 SpdyStreamId last_push_promise_stream_;
546 SpdyStreamId last_push_promise_promised_stream_;
547 int data_bytes_;
548 int fin_frame_count_; // The count of RST_STREAM type frames received.
549 string fin_opaque_data_;
550 int fin_flag_count_; // The count of frames with the FIN flag set.
551 int zero_length_data_frame_count_; // The count of zero-length data frames.
552 int control_frame_header_data_count_; // The count of chunks received.
553 // The count of zero-length control frame header data chunks received.
554 int zero_length_control_frame_header_data_count_;
555 int data_frame_count_;
556 size_t last_payload_len_;
557 size_t last_frame_len_;
559 // Header block streaming state:
560 scoped_ptr<char[]> header_buffer_;
561 size_t header_buffer_length_;
562 size_t header_buffer_size_;
563 SpdyStreamId header_stream_id_;
564 SpdyFrameType header_control_type_;
565 bool header_buffer_valid_;
566 SpdyHeaderBlock headers_;
569 class SpdyFramerPeer {
570 public:
571 static size_t ControlFrameBufferSize() {
572 return SpdyFramer::kControlFrameBufferSize;
574 static size_t GetNumberRequiredContinuationFrames(SpdyFramer* framer,
575 size_t size) {
576 return framer->GetNumberRequiredContinuationFrames(size);
580 // Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
581 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
582 const SpdyFramer& framer) {
583 SpdyFrameReader reader(frame->data(), frame->size());
584 if (framer.protocol_version() > SPDY3) {
585 reader.Seek(3); // Seek past the frame length.
586 } else {
587 reader.Seek(2); // Seek past the frame length.
589 SpdyFrameType frame_type;
590 if (framer.protocol_version() > SPDY3) {
591 uint8 serialized_type;
592 reader.ReadUInt8(&serialized_type);
593 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
594 serialized_type);
595 DCHECK_EQ(HEADERS, frame_type);
596 uint8 flags;
597 reader.ReadUInt8(&flags);
598 if (flags & HEADERS_FLAG_PRIORITY) {
599 frame_type = SYN_STREAM;
601 } else {
602 uint16 serialized_type;
603 reader.ReadUInt16(&serialized_type);
604 frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
605 serialized_type);
606 DCHECK(frame_type == HEADERS ||
607 frame_type == SYN_STREAM) << frame_type;
610 if (frame_type == SYN_STREAM) {
611 return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
612 frame->size() - framer.GetSynStreamMinimumSize());
613 } else {
614 return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
615 frame->size() - framer.GetHeadersMinimumSize());
619 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
620 protected:
621 void SetUp() override {
622 spdy_version_ = GetParam();
623 spdy_version_ch_ = static_cast<unsigned char>(
624 SpdyConstants::SerializeMajorVersion(spdy_version_));
627 void CompareFrame(const string& description,
628 const SpdyFrame& actual_frame,
629 const unsigned char* expected,
630 const int expected_len) {
631 const unsigned char* actual =
632 reinterpret_cast<const unsigned char*>(actual_frame.data());
633 CompareCharArraysWithHexError(
634 description, actual, actual_frame.size(), expected, expected_len);
637 void CompareFrames(const string& description,
638 const SpdyFrame& expected_frame,
639 const SpdyFrame& actual_frame) {
640 CompareCharArraysWithHexError(
641 description,
642 reinterpret_cast<const unsigned char*>(expected_frame.data()),
643 expected_frame.size(),
644 reinterpret_cast<const unsigned char*>(actual_frame.data()),
645 actual_frame.size());
648 // Returns true if the two header blocks have equivalent content.
649 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
650 const SpdyHeaderBlock* actual) {
651 if (expected->size() != actual->size()) {
652 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
653 << actual->size() << ".";
654 return false;
656 for (SpdyHeaderBlock::const_iterator it = expected->begin();
657 it != expected->end();
658 ++it) {
659 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
660 if (it2 == actual->end()) {
661 LOG(ERROR) << "Expected header name '" << it->first << "'.";
662 return false;
664 if (it->second.compare(it2->second) != 0) {
665 LOG(ERROR) << "Expected header named '" << it->first
666 << "' to have a value of '" << it->second
667 << "'. The actual value received was '" << it2->second
668 << "'.";
669 return false;
672 return true;
675 bool IsSpdy2() { return spdy_version_ == SPDY2; }
676 bool IsSpdy3() { return spdy_version_ == SPDY3; }
677 bool IsSpdy4() { return spdy_version_ == SPDY4; }
679 // Version of SPDY protocol to be used.
680 SpdyMajorVersion spdy_version_;
681 unsigned char spdy_version_ch_;
684 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
685 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
686 SpdyFramerTest,
687 ::testing::Values(SPDY2, SPDY3, SPDY4));
689 // Test that we ignore cookie where both name and value are empty.
690 TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
691 if (spdy_version_ > SPDY3) {
692 // Not implemented for hpack.
693 return;
696 SpdyFramer framer(spdy_version_);
697 framer.set_enable_compression(true);
698 SpdyHeadersIR headers(1);
699 headers.set_priority(1);
700 headers.SetHeader("cookie",
701 "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
702 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
703 EXPECT_TRUE(frame.get() != NULL);
705 TestSpdyVisitor visitor(spdy_version_);
706 visitor.use_compression_ = true;
707 visitor.SimulateInFramer(
708 reinterpret_cast<unsigned char*>(frame->data()),
709 frame->size());
711 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
712 EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
713 &visitor.headers_));
714 EXPECT_EQ(1u, visitor.headers_.size());
715 EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
718 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
719 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
720 SpdyFramer framer(spdy_version_);
721 framer.set_enable_compression(false);
723 // Encode the header block into a Headers frame.
724 SpdyHeadersIR headers(1);
725 headers.set_priority(1);
726 headers.SetHeader("alpha", "beta");
727 headers.SetHeader("gamma", "charlie");
728 headers.SetHeader("cookie", "key1=value1; key2=value2");
729 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
730 EXPECT_TRUE(frame.get() != NULL);
732 TestSpdyVisitor visitor(spdy_version_);
733 visitor.use_compression_ = false;
734 visitor.SimulateInFramer(
735 reinterpret_cast<unsigned char*>(frame->data()),
736 frame->size());
738 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
739 EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
740 &visitor.headers_));
743 // Test that if there's not a full frame, we fail to parse it.
744 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
745 SpdyFramer framer(spdy_version_);
746 framer.set_enable_compression(false);
748 // Encode the header block into a Headers frame.
749 SpdyHeadersIR headers(1);
750 headers.set_priority(1);
751 headers.SetHeader("alpha", "beta");
752 headers.SetHeader("gamma", "charlie");
753 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
754 EXPECT_TRUE(frame.get() != NULL);
756 TestSpdyVisitor visitor(spdy_version_);
757 visitor.use_compression_ = false;
758 visitor.SimulateInFramer(
759 reinterpret_cast<unsigned char*>(frame->data()),
760 frame->size() - 2);
762 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
763 EXPECT_EQ(0u, visitor.headers_.size());
766 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
767 // (but don't crash).
768 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
769 if (spdy_version_ > SPDY3) {
770 return;
772 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
773 SpdyFramer framer(spdy_version_);
774 framer.set_visitor(&visitor);
776 SpdySynReplyIR syn_reply(0);
777 syn_reply.SetHeader("alpha", "beta");
778 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
779 ASSERT_TRUE(frame.get() != NULL);
781 // We shouldn't have to read the whole frame before we signal an error.
782 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
783 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
784 EXPECT_TRUE(framer.HasError());
785 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
786 << SpdyFramer::ErrorCodeToString(framer.error_code());
789 // Test that if we receive a HEADERS with stream ID zero, we signal an error
790 // (but don't crash).
791 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
792 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
793 SpdyFramer framer(spdy_version_);
794 framer.set_visitor(&visitor);
796 SpdyHeadersIR headers_ir(0);
797 headers_ir.SetHeader("alpha", "beta");
798 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
799 ASSERT_TRUE(frame.get() != NULL);
801 // We shouldn't have to read the whole frame before we signal an error.
802 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
803 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
804 EXPECT_TRUE(framer.HasError());
805 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
806 << SpdyFramer::ErrorCodeToString(framer.error_code());
809 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
810 // error (but don't crash).
811 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
812 if (spdy_version_ <= SPDY3) {
813 return;
816 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
817 SpdyFramer framer(spdy_version_);
818 framer.set_visitor(&visitor);
820 SpdyPushPromiseIR push_promise(0, 4);
821 push_promise.SetHeader("alpha", "beta");
822 scoped_ptr<SpdySerializedFrame> frame(
823 framer.SerializePushPromise(push_promise));
824 ASSERT_TRUE(frame.get() != NULL);
826 // We shouldn't have to read the whole frame before we signal an error.
827 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
828 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
829 EXPECT_TRUE(framer.HasError());
830 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
831 << SpdyFramer::ErrorCodeToString(framer.error_code());
834 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
835 // signal an error (but don't crash).
836 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
837 if (spdy_version_ <= SPDY3) {
838 return;
841 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
842 SpdyFramer framer(spdy_version_);
843 framer.set_visitor(&visitor);
845 SpdyPushPromiseIR push_promise(3, 0);
846 push_promise.SetHeader("alpha", "beta");
847 scoped_ptr<SpdySerializedFrame> frame(
848 framer.SerializePushPromise(push_promise));
849 ASSERT_TRUE(frame.get() != NULL);
851 // We shouldn't have to read the whole frame before we signal an error.
852 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
853 EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
854 EXPECT_TRUE(framer.HasError());
855 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
856 << SpdyFramer::ErrorCodeToString(framer.error_code());
859 TEST_P(SpdyFramerTest, DuplicateHeader) {
860 if (spdy_version_ > SPDY3) {
861 // TODO(jgraettinger): Punting on this because we haven't determined
862 // whether duplicate HPACK headers other than Cookie are an error.
863 // If they are, this will need to be updated to use HpackOutputStream.
864 return;
866 SpdyFramer framer(spdy_version_);
867 // Frame builder with plentiful buffer size.
868 SpdyFrameBuilder frame(1024, spdy_version_);
869 if (spdy_version_ <= SPDY3) {
870 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
871 frame.WriteUInt32(3); // stream_id
872 frame.WriteUInt32(0); // associated stream id
873 frame.WriteUInt16(0); // Priority.
874 } else {
875 frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
876 frame.WriteUInt32(framer.GetHighestPriority());
879 if (IsSpdy2()) {
880 frame.WriteUInt16(2); // Number of headers.
881 frame.WriteStringPiece16("name");
882 frame.WriteStringPiece16("value1");
883 frame.WriteStringPiece16("name");
884 frame.WriteStringPiece16("value2");
885 } else {
886 frame.WriteUInt32(2); // Number of headers.
887 frame.WriteStringPiece32("name");
888 frame.WriteStringPiece32("value1");
889 frame.WriteStringPiece32("name");
890 frame.WriteStringPiece32("value2");
892 // write the length
893 frame.RewriteLength(framer);
895 SpdyHeaderBlock new_headers;
896 framer.set_enable_compression(false);
897 scoped_ptr<SpdyFrame> control_frame(frame.take());
898 base::StringPiece serialized_headers =
899 GetSerializedHeaders(control_frame.get(), framer);
900 // This should fail because duplicate headers are verboten by the spec.
901 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
902 serialized_headers.size(),
903 &new_headers));
906 TEST_P(SpdyFramerTest, MultiValueHeader) {
907 SpdyFramer framer(spdy_version_);
908 // Frame builder with plentiful buffer size.
909 SpdyFrameBuilder frame(1024, spdy_version_);
910 if (spdy_version_ <= SPDY3) {
911 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
912 frame.WriteUInt32(3); // stream_id
913 frame.WriteUInt32(0); // associated stream id
914 frame.WriteUInt16(0); // Priority.
915 } else {
916 frame.BeginNewFrame(framer,
917 HEADERS,
918 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
920 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
921 frame.WriteUInt8(255); // Priority weight.
924 string value("value1\0value2", 13);
925 if (IsSpdy2()) {
926 frame.WriteUInt16(1); // Number of headers.
927 frame.WriteStringPiece16("name");
928 frame.WriteStringPiece16(value);
929 } else if (spdy_version_ > SPDY3) {
930 // TODO(jgraettinger): If this pattern appears again, move to test class.
931 std::map<string, string> header_set;
932 header_set["name"] = value;
933 string buffer;
934 HpackEncoder encoder(ObtainHpackHuffmanTable());
935 encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
936 frame.WriteBytes(&buffer[0], buffer.size());
937 } else {
938 frame.WriteUInt32(1); // Number of headers.
939 frame.WriteStringPiece32("name");
940 frame.WriteStringPiece32(value);
942 // write the length
943 frame.RewriteLength(framer);
945 framer.set_enable_compression(false);
946 scoped_ptr<SpdyFrame> control_frame(frame.take());
948 TestSpdyVisitor visitor(spdy_version_);
949 visitor.use_compression_ = false;
950 visitor.SimulateInFramer(
951 reinterpret_cast<unsigned char*>(control_frame->data()),
952 control_frame->size());
954 EXPECT_THAT(visitor.headers_,
955 testing::ElementsAre(testing::Pair("name", value)));
958 TEST_P(SpdyFramerTest, BasicCompression) {
959 if (spdy_version_ > SPDY3) {
960 // Deflate compression doesn't apply to HPACK.
961 return;
963 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
964 SpdyFramer framer(spdy_version_);
965 framer.set_debug_visitor(visitor.get());
966 SpdySynStreamIR syn_stream(1);
967 syn_stream.set_priority(1);
968 syn_stream.SetHeader("server", "SpdyServer 1.0");
969 syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
970 syn_stream.SetHeader("status", "200");
971 syn_stream.SetHeader("version", "HTTP/1.1");
972 syn_stream.SetHeader("content-type", "text/html");
973 syn_stream.SetHeader("content-length", "12");
974 scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
975 size_t uncompressed_size1 = visitor->last_payload_len_;
976 size_t compressed_size1 =
977 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
978 if (IsSpdy2()) {
979 EXPECT_EQ(139u, uncompressed_size1);
980 #if defined(USE_SYSTEM_ZLIB)
981 EXPECT_EQ(155u, compressed_size1);
982 #else // !defined(USE_SYSTEM_ZLIB)
983 EXPECT_EQ(135u, compressed_size1);
984 #endif // !defined(USE_SYSTEM_ZLIB)
985 } else {
986 EXPECT_EQ(165u, uncompressed_size1);
987 #if defined(USE_SYSTEM_ZLIB)
988 EXPECT_EQ(181u, compressed_size1);
989 #else // !defined(USE_SYSTEM_ZLIB)
990 EXPECT_EQ(117u, compressed_size1);
991 #endif // !defined(USE_SYSTEM_ZLIB)
993 scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
994 size_t uncompressed_size2 = visitor->last_payload_len_;
995 size_t compressed_size2 =
996 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
998 // Expect the second frame to be more compact than the first.
999 EXPECT_LE(frame2->size(), frame1->size());
1001 // Decompress the first frame
1002 scoped_ptr<SpdyFrame> frame3(
1003 SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
1005 // Decompress the second frame
1006 visitor.reset(new TestSpdyVisitor(spdy_version_));
1007 framer.set_debug_visitor(visitor.get());
1008 scoped_ptr<SpdyFrame> frame4(
1009 SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
1010 size_t uncompressed_size4 =
1011 frame4->size() - framer.GetSynStreamMinimumSize();
1012 size_t compressed_size4 =
1013 visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
1014 if (IsSpdy2()) {
1015 EXPECT_EQ(139u, uncompressed_size4);
1016 #if defined(USE_SYSTEM_ZLIB)
1017 EXPECT_EQ(149u, compressed_size4);
1018 #else // !defined(USE_SYSTEM_ZLIB)
1019 EXPECT_EQ(101u, compressed_size4);
1020 #endif // !defined(USE_SYSTEM_ZLIB)
1021 } else {
1022 EXPECT_EQ(165u, uncompressed_size4);
1023 #if defined(USE_SYSTEM_ZLIB)
1024 EXPECT_EQ(175u, compressed_size4);
1025 #else // !defined(USE_SYSTEM_ZLIB)
1026 EXPECT_EQ(102u, compressed_size4);
1027 #endif // !defined(USE_SYSTEM_ZLIB)
1030 EXPECT_EQ(uncompressed_size1, uncompressed_size2);
1031 EXPECT_EQ(uncompressed_size1, uncompressed_size4);
1032 EXPECT_EQ(compressed_size2, compressed_size4);
1034 // Expect frames 3 & 4 to be the same.
1035 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
1037 // Expect frames 3 to be the same as a uncompressed frame created
1038 // from scratch.
1039 framer.set_enable_compression(false);
1040 scoped_ptr<SpdyFrame> uncompressed_frame(
1041 framer.SerializeSynStream(syn_stream));
1042 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
1045 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1046 // See crbug.com/172383
1047 SpdyHeadersIR headers(1);
1048 headers.SetHeader("server", "SpdyServer 1.0");
1049 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1050 headers.SetHeader("status", "200");
1051 headers.SetHeader("version", "HTTP/1.1");
1052 headers.SetHeader("content-type", "text/html");
1053 headers.SetHeader("content-length", "12");
1054 headers.SetHeader("x-empty-header", "");
1056 SpdyFramer framer(spdy_version_);
1057 framer.set_enable_compression(true);
1058 scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
1061 TEST_P(SpdyFramerTest, Basic) {
1062 const unsigned char kV2Input[] = {
1063 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1064 0x00, 0x00, 0x00, 0x14,
1065 0x00, 0x00, 0x00, 0x01,
1066 0x00, 0x00, 0x00, 0x00,
1067 0x00, 0x00, 0x00, 0x01,
1068 0x00, 0x02, 'h', 'h',
1069 0x00, 0x02, 'v', 'v',
1071 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1072 0x00, 0x00, 0x00, 0x18,
1073 0x00, 0x00, 0x00, 0x01,
1074 0x00, 0x00, 0x00, 0x02,
1075 0x00, 0x02, 'h', '2',
1076 0x00, 0x02, 'v', '2',
1077 0x00, 0x02, 'h', '3',
1078 0x00, 0x02, 'v', '3',
1080 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1081 0x00, 0x00, 0x00, 0x0c,
1082 0xde, 0xad, 0xbe, 0xef,
1083 0xde, 0xad, 0xbe, 0xef,
1084 0xde, 0xad, 0xbe, 0xef,
1086 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1087 0x00, 0x00, 0x00, 0x0c,
1088 0x00, 0x00, 0x00, 0x03,
1089 0x00, 0x00, 0x00, 0x00,
1090 0x00, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1093 0x00, 0x00, 0x00, 0x08,
1094 0xde, 0xad, 0xbe, 0xef,
1095 0xde, 0xad, 0xbe, 0xef,
1097 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1098 0x00, 0x00, 0x00, 0x04,
1099 0xde, 0xad, 0xbe, 0xef,
1101 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1102 0x00, 0x00, 0x00, 0x08,
1103 0x00, 0x00, 0x00, 0x01,
1104 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1106 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1107 0x00, 0x00, 0x00, 0x00,
1109 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1110 0x00, 0x00, 0x00, 0x08,
1111 0x00, 0x00, 0x00, 0x03,
1112 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1115 const unsigned char kV3Input[] = {
1116 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1117 0x00, 0x00, 0x00, 0x1a,
1118 0x00, 0x00, 0x00, 0x01,
1119 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x01, 0x00, 0x00,
1122 0x00, 0x02, 'h', 'h',
1123 0x00, 0x00, 0x00, 0x02,
1124 'v', 'v',
1126 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
1127 0x00, 0x00, 0x00, 0x20,
1128 0x00, 0x00, 0x00, 0x01,
1129 0x00, 0x00, 0x00, 0x02,
1130 0x00, 0x00, 0x00, 0x02,
1131 'h', '2',
1132 0x00, 0x00, 0x00, 0x02,
1133 'v', '2', 0x00, 0x00,
1134 0x00, 0x02, 'h', '3',
1135 0x00, 0x00, 0x00, 0x02,
1136 'v', '3',
1138 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1139 0x00, 0x00, 0x00, 0x0c,
1140 0xde, 0xad, 0xbe, 0xef,
1141 0xde, 0xad, 0xbe, 0xef,
1142 0xde, 0xad, 0xbe, 0xef,
1144 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
1145 0x00, 0x00, 0x00, 0x0e,
1146 0x00, 0x00, 0x00, 0x03,
1147 0x00, 0x00, 0x00, 0x00,
1148 0x00, 0x00, 0x00, 0x00,
1149 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1152 0x00, 0x00, 0x00, 0x08,
1153 0xde, 0xad, 0xbe, 0xef,
1154 0xde, 0xad, 0xbe, 0xef,
1156 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1157 0x00, 0x00, 0x00, 0x04,
1158 0xde, 0xad, 0xbe, 0xef,
1160 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
1161 0x00, 0x00, 0x00, 0x08,
1162 0x00, 0x00, 0x00, 0x01,
1163 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1165 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
1166 0x00, 0x00, 0x00, 0x00,
1168 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
1169 0x00, 0x00, 0x00, 0x08,
1170 0x00, 0x00, 0x00, 0x03,
1171 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
1174 // SYN_STREAM doesn't exist in SPDY4, so instead we send
1175 // HEADERS frames with PRIORITY and END_HEADERS set.
1176 const unsigned char kV4Input[] = {
1177 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1178 0x24, 0x00, 0x00, 0x00,
1179 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1180 0x00, 0x82, // :method: GET
1182 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1183 0x04, 0x00, 0x00, 0x00, // Stream 1
1184 0x01, 0x8c, // :status: 200
1186 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1187 0x00, 0x00, 0x00, 0x00,
1188 0x01, 0xde, 0xad, 0xbe,
1189 0xef, 0xde, 0xad, 0xbe,
1190 0xef, 0xde, 0xad, 0xbe,
1191 0xef,
1193 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1194 0x24, 0x00, 0x00, 0x00,
1195 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
1196 0x00, 0x82, // :method: GET
1198 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
1199 0x00, 0x00, 0x00, 0x00,
1200 0x03, 0xde, 0xad, 0xbe,
1201 0xef, 0xde, 0xad, 0xbe,
1202 0xef,
1204 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
1205 0x00, 0x00, 0x00, 0x00,
1206 0x01, 0xde, 0xad, 0xbe,
1207 0xef,
1209 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
1210 0x00, 0x00, 0x00, 0x00,
1211 0x01, 0x00, 0x00, 0x00,
1212 0x08, // RST_STREAM_CANCEL
1214 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
1215 0x00, 0x00, 0x00, 0x00,
1216 0x03,
1218 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
1219 0x00, 0x00, 0x00, 0x00,
1220 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
1221 0x08, 0x52, 0x45, 0x53, // opaque data
1222 0x45, 0x54, 0x53, 0x54,
1223 0x52, 0x45, 0x41, 0x4d,
1226 TestSpdyVisitor visitor(spdy_version_);
1227 if (IsSpdy2()) {
1228 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1229 } else if (IsSpdy3()) {
1230 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1231 } else {
1232 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1235 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1236 EXPECT_EQ(24, visitor.data_bytes_);
1237 EXPECT_EQ(0, visitor.error_count_);
1238 EXPECT_EQ(2, visitor.fin_frame_count_);
1240 if (IsSpdy4()) {
1241 EXPECT_EQ(3, visitor.headers_frame_count_);
1242 EXPECT_EQ(0, visitor.syn_frame_count_);
1243 base::StringPiece reset_stream = "RESETSTREAM";
1244 EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
1245 } else {
1246 EXPECT_EQ(1, visitor.headers_frame_count_);
1247 EXPECT_EQ(2, visitor.syn_frame_count_);
1248 EXPECT_TRUE(visitor.fin_opaque_data_.empty());
1251 EXPECT_EQ(0, visitor.fin_flag_count_);
1252 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
1253 EXPECT_EQ(4, visitor.data_frame_count_);
1254 visitor.fin_opaque_data_.clear();
1257 // Test that the FIN flag on a data frame signifies EOF.
1258 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1259 const unsigned char kV2Input[] = {
1260 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1261 0x00, 0x00, 0x00, 0x14,
1262 0x00, 0x00, 0x00, 0x01,
1263 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x01,
1265 0x00, 0x02, 'h', 'h',
1266 0x00, 0x02, 'v', 'v',
1268 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1269 0x00, 0x00, 0x00, 0x10,
1270 0x00, 0x00, 0x00, 0x01,
1271 0x00, 0x00, 0x00, 0x01,
1272 0x00, 0x02, 'a', 'a',
1273 0x00, 0x02, 'b', 'b',
1275 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1276 0x00, 0x00, 0x00, 0x0c,
1277 0xde, 0xad, 0xbe, 0xef,
1278 0xde, 0xad, 0xbe, 0xef,
1279 0xde, 0xad, 0xbe, 0xef,
1281 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1282 0x01, 0x00, 0x00, 0x04,
1283 0xde, 0xad, 0xbe, 0xef,
1285 const unsigned char kV3Input[] = {
1286 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
1287 0x00, 0x00, 0x00, 0x1a,
1288 0x00, 0x00, 0x00, 0x01,
1289 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00,
1291 0x00, 0x01, 0x00, 0x00,
1292 0x00, 0x02, 'h', 'h',
1293 0x00, 0x00, 0x00, 0x02,
1294 'v', 'v',
1296 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
1297 0x00, 0x00, 0x00, 0x14,
1298 0x00, 0x00, 0x00, 0x01,
1299 0x00, 0x00, 0x00, 0x01,
1300 0x00, 0x00, 0x00, 0x02,
1301 'a', 'a', 0x00, 0x00,
1302 0x00, 0x02, 'b', 'b',
1304 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
1305 0x00, 0x00, 0x00, 0x0c,
1306 0xde, 0xad, 0xbe, 0xef,
1307 0xde, 0xad, 0xbe, 0xef,
1308 0xde, 0xad, 0xbe, 0xef,
1310 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
1311 0x01, 0x00, 0x00, 0x04,
1312 0xde, 0xad, 0xbe, 0xef,
1315 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1316 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1317 const unsigned char kV4Input[] = {
1318 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1319 0x24, 0x00, 0x00, 0x00, // Stream 1
1320 0x01, 0x00, 0x00, 0x00, // Priority 0
1321 0x00, 0x82, // :method: GET
1323 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
1324 0x04, 0x00, 0x00, 0x00, // Stream 1
1325 0x01, 0x8c, // :status: 200
1327 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
1328 0x00, 0x00, 0x00, 0x00,
1329 0x01, 0xde, 0xad, 0xbe,
1330 0xef, 0xde, 0xad, 0xbe,
1331 0xef, 0xde, 0xad, 0xbe,
1332 0xef,
1334 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
1335 0x01, 0x00, 0x00, 0x00,
1336 0x01, 0xde, 0xad, 0xbe,
1337 0xef,
1340 TestSpdyVisitor visitor(spdy_version_);
1341 if (IsSpdy2()) {
1342 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1343 } else if (IsSpdy3()) {
1344 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1345 } else {
1346 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1349 EXPECT_EQ(0, visitor.error_count_);
1350 if (IsSpdy4()) {
1351 EXPECT_EQ(0, visitor.syn_frame_count_);
1352 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1353 EXPECT_EQ(2, visitor.headers_frame_count_);
1354 } else {
1355 EXPECT_EQ(1, visitor.syn_frame_count_);
1356 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1357 EXPECT_EQ(0, visitor.headers_frame_count_);
1359 EXPECT_EQ(16, visitor.data_bytes_);
1360 EXPECT_EQ(0, visitor.fin_frame_count_);
1361 EXPECT_EQ(0, visitor.fin_flag_count_);
1362 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1363 EXPECT_EQ(2, visitor.data_frame_count_);
1366 // Test that the FIN flag on a SYN reply frame signifies EOF.
1367 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
1368 const unsigned char kV2Input[] = {
1369 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1370 0x01, 0x00, 0x00, 0x00,
1371 0x14, 0x00, 0x00, 0x00,
1372 0x01, 0x00, 0x00, 0x00,
1373 0x00, 0x00, 0x00, 0x00,
1374 0x01, 0x00, 0x02, 'h',
1375 'h', 0x00, 0x02, 'v',
1376 'v',
1378 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1379 0x02, 0x01, 0x00, 0x00,
1380 0x10, 0x00, 0x00, 0x00,
1381 0x01, 0x00, 0x00, 0x00,
1382 0x01, 0x00, 0x02, 'a',
1383 'a', 0x00, 0x02, 'b',
1384 'b',
1386 const unsigned char kV3Input[] = {
1387 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
1388 0x01, 0x00, 0x00, 0x00,
1389 0x1a, 0x00, 0x00, 0x00,
1390 0x01, 0x00, 0x00, 0x00,
1391 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x01, 0x00,
1393 0x00, 0x00, 0x02, 'h',
1394 'h', 0x00, 0x00, 0x00,
1395 0x02, 'v', 'v',
1397 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
1398 0x02, 0x01, 0x00, 0x00,
1399 0x14, 0x00, 0x00, 0x00,
1400 0x01, 0x00, 0x00, 0x00,
1401 0x01, 0x00, 0x00, 0x00,
1402 0x02, 'a', 'a', 0x00,
1403 0x00, 0x00, 0x02, 'b',
1404 'b',
1407 // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
1408 // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
1409 const unsigned char kV4Input[] = {
1410 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
1411 0x24, 0x00, 0x00, 0x00,
1412 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
1413 0x00, 0x82, // :method: GET
1415 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
1416 0x05, 0x00, 0x00, 0x00,
1417 0x01, 0x8c, // Stream 1, :status: 200
1420 TestSpdyVisitor visitor(spdy_version_);
1421 if (IsSpdy2()) {
1422 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
1423 } else if (IsSpdy3()) {
1424 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
1425 } else {
1426 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
1429 EXPECT_EQ(0, visitor.error_count_);
1430 if (IsSpdy4()) {
1431 EXPECT_EQ(0, visitor.syn_frame_count_);
1432 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1433 EXPECT_EQ(2, visitor.headers_frame_count_);
1434 } else {
1435 EXPECT_EQ(1, visitor.syn_frame_count_);
1436 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
1437 EXPECT_EQ(0, visitor.headers_frame_count_);
1439 EXPECT_EQ(0, visitor.data_bytes_);
1440 EXPECT_EQ(0, visitor.fin_frame_count_);
1441 EXPECT_EQ(1, visitor.fin_flag_count_);
1442 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1443 EXPECT_EQ(0, visitor.data_frame_count_);
1446 TEST_P(SpdyFramerTest, HeaderCompression) {
1447 if (spdy_version_ > SPDY3) {
1448 // Deflate compression doesn't apply to HPACK.
1449 return;
1451 SpdyFramer send_framer(spdy_version_);
1452 SpdyFramer recv_framer(spdy_version_);
1454 send_framer.set_enable_compression(true);
1455 recv_framer.set_enable_compression(true);
1457 const char kHeader1[] = "header1";
1458 const char kHeader2[] = "header2";
1459 const char kHeader3[] = "header3";
1460 const char kValue1[] = "value1";
1461 const char kValue2[] = "value2";
1462 const char kValue3[] = "value3";
1464 // SYN_STREAM #1
1465 SpdyHeaderBlock block;
1466 block[kHeader1] = kValue1;
1467 block[kHeader2] = kValue2;
1468 SpdySynStreamIR syn_ir_1(1);
1469 syn_ir_1.set_name_value_block(block);
1470 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
1471 EXPECT_TRUE(syn_frame_1.get() != NULL);
1473 // SYN_STREAM #2
1474 block[kHeader3] = kValue3;
1475 SpdySynStreamIR syn_stream(3);
1476 syn_stream.set_name_value_block(block);
1477 scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
1478 EXPECT_TRUE(syn_frame_2.get() != NULL);
1480 // Now start decompressing
1481 scoped_ptr<SpdyFrame> decompressed;
1482 scoped_ptr<SpdyFrame> uncompressed;
1483 base::StringPiece serialized_headers;
1484 SpdyHeaderBlock decompressed_headers;
1486 // Decompress SYN_STREAM #1
1487 decompressed.reset(
1488 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
1489 EXPECT_TRUE(decompressed.get() != NULL);
1490 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1491 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1492 serialized_headers.size(),
1493 &decompressed_headers));
1494 EXPECT_EQ(2u, decompressed_headers.size());
1495 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1496 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1498 // Decompress SYN_STREAM #2
1499 decompressed.reset(
1500 SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
1501 EXPECT_TRUE(decompressed.get() != NULL);
1502 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
1503 decompressed_headers.clear();
1504 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
1505 serialized_headers.size(),
1506 &decompressed_headers));
1507 EXPECT_EQ(3u, decompressed_headers.size());
1508 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
1509 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
1510 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
1513 // Verify we can decompress the stream even if handed over to the
1514 // framer 1 byte at a time.
1515 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1516 SpdyFramer send_framer(spdy_version_);
1518 send_framer.set_enable_compression(true);
1520 const char kHeader1[] = "header1";
1521 const char kHeader2[] = "header2";
1522 const char kValue1[] = "value1";
1523 const char kValue2[] = "value2";
1525 SpdyHeadersIR headers(1);
1526 headers.SetHeader(kHeader1, kValue1);
1527 headers.SetHeader(kHeader2, kValue2);
1528 scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
1529 EXPECT_TRUE(headers_frame.get() != NULL);
1531 const char bytes[] = "this is a test test test test test!";
1532 SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
1533 data_ir.set_fin(true);
1534 scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
1535 EXPECT_TRUE(send_frame.get() != NULL);
1537 // Run the inputs through the framer.
1538 TestSpdyVisitor visitor(spdy_version_);
1539 visitor.use_compression_ = true;
1540 const unsigned char* data;
1541 data = reinterpret_cast<const unsigned char*>(headers_frame->data());
1542 for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
1543 visitor.SimulateInFramer(data + idx, 1);
1544 ASSERT_EQ(0, visitor.error_count_);
1546 data = reinterpret_cast<const unsigned char*>(send_frame->data());
1547 for (size_t idx = 0; idx < send_frame->size(); ++idx) {
1548 visitor.SimulateInFramer(data + idx, 1);
1549 ASSERT_EQ(0, visitor.error_count_);
1552 EXPECT_EQ(0, visitor.error_count_);
1553 EXPECT_EQ(0, visitor.syn_frame_count_);
1554 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
1555 EXPECT_EQ(1, visitor.headers_frame_count_);
1556 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1557 EXPECT_EQ(0, visitor.fin_frame_count_);
1558 EXPECT_EQ(0, visitor.fin_flag_count_);
1559 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
1560 EXPECT_EQ(1, visitor.data_frame_count_);
1563 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1564 SpdyFramer framer(spdy_version_);
1565 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
1566 SpdyWindowUpdateIR(1, 0x12345678)));
1568 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1569 const unsigned char kV3FrameData[] = { // Also applies for V2.
1570 0x80, spdy_version_ch_, 0x00, 0x09,
1571 0x00, 0x00, 0x00, 0x08,
1572 0x00, 0x00, 0x00, 0x01,
1573 0x12, 0x34, 0x56, 0x78
1575 const unsigned char kV4FrameData[] = {
1576 0x00, 0x00, 0x04, 0x08,
1577 0x00, 0x00, 0x00, 0x00,
1578 0x01, 0x12, 0x34, 0x56,
1579 0x78
1582 if (IsSpdy4()) {
1583 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1584 } else {
1585 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1589 TEST_P(SpdyFramerTest, CreateDataFrame) {
1590 SpdyFramer framer(spdy_version_);
1593 const char kDescription[] = "'hello' data frame, no FIN";
1594 const unsigned char kV3FrameData[] = { // Also applies for V2.
1595 0x00, 0x00, 0x00, 0x01,
1596 0x00, 0x00, 0x00, 0x05,
1597 'h', 'e', 'l', 'l',
1600 const unsigned char kV4FrameData[] = {
1601 0x00, 0x00, 0x05, 0x00,
1602 0x00, 0x00, 0x00, 0x00,
1603 0x01, 'h', 'e', 'l',
1604 'l', 'o'
1606 const char bytes[] = "hello";
1608 SpdyDataIR data_ir(1, bytes);
1609 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1610 if (IsSpdy4()) {
1611 CompareFrame(
1612 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1613 } else {
1614 CompareFrame(
1615 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1618 SpdyDataIR data_header_ir(1);
1619 data_header_ir.SetDataShallow(bytes);
1620 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
1621 data_header_ir));
1622 CompareCharArraysWithHexError(
1623 kDescription,
1624 reinterpret_cast<const unsigned char*>(frame->data()),
1625 framer.GetDataFrameMinimumSize(),
1626 IsSpdy4() ? kV4FrameData : kV3FrameData,
1627 framer.GetDataFrameMinimumSize());
1631 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1632 const unsigned char kV3FrameData[] = { // Also applies for V2.
1633 0x00, 0x00, 0x00, 0x01,
1634 0x00, 0x00, 0x00, 0x05,
1635 'h', 'e', 'l', 'l',
1639 const unsigned char kV4FrameData[] = {
1640 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
1641 0x08, 0x00, 0x00, 0x00,
1642 0x01, 0xf7, // Pad length field.
1643 'h', 'e', 'l', 'l', // Data
1644 'o',
1645 // Padding of 247 0x00(s).
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1668 const char bytes[] = "hello";
1670 SpdyDataIR data_ir(1, bytes);
1671 // 247 zeros and the pad length field make the overall padding to be 248
1672 // bytes.
1673 data_ir.set_padding_len(248);
1674 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1675 if (IsSpdy4()) {
1676 CompareFrame(
1677 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1678 } else {
1679 CompareFrame(
1680 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1683 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1684 CompareCharArraysWithHexError(
1685 kDescription,
1686 reinterpret_cast<const unsigned char*>(frame->data()),
1687 framer.GetDataFrameMinimumSize(),
1688 IsSpdy4() ? kV4FrameData : kV3FrameData,
1689 framer.GetDataFrameMinimumSize());
1693 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1694 const unsigned char kV3FrameData[] = { // Also applies for V2.
1695 0x00, 0x00, 0x00, 0x01,
1696 0x00, 0x00, 0x00, 0x05,
1697 'h', 'e', 'l', 'l',
1701 const unsigned char kV4FrameData[] = {
1702 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
1703 0x08, 0x00, 0x00, 0x00,
1704 0x01, 0x07, // Pad length field.
1705 'h', 'e', 'l', 'l', // Data
1706 'o',
1707 0x00, 0x00, 0x00, 0x00, // Padding
1708 0x00, 0x00, 0x00
1710 const char bytes[] = "hello";
1712 SpdyDataIR data_ir(1, bytes);
1713 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1714 data_ir.set_padding_len(8);
1715 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1716 if (IsSpdy4()) {
1717 CompareFrame(
1718 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1719 } else {
1720 CompareFrame(
1721 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1726 const char kDescription[] =
1727 "'hello' data frame with 1 byte padding, no FIN";
1728 const unsigned char kV3FrameData[] = { // Also applies for V2.
1729 0x00, 0x00, 0x00, 0x01,
1730 0x00, 0x00, 0x00, 0x05,
1731 'h', 'e', 'l', 'l',
1735 const unsigned char kV4FrameData[] = {
1736 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
1737 0x08, 0x00, 0x00, 0x00,
1738 0x01, 0x00, // Pad length field.
1739 'h', 'e', 'l', 'l', // Data
1740 'o',
1742 const char bytes[] = "hello";
1744 SpdyDataIR data_ir(1, bytes);
1745 // The pad length field itself is used for the 1-byte padding and no padding
1746 // payload is needed.
1747 data_ir.set_padding_len(1);
1748 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1749 if (IsSpdy4()) {
1750 CompareFrame(
1751 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1752 } else {
1753 CompareFrame(
1754 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1757 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1758 CompareCharArraysWithHexError(
1759 kDescription,
1760 reinterpret_cast<const unsigned char*>(frame->data()),
1761 framer.GetDataFrameMinimumSize(),
1762 IsSpdy4() ? kV4FrameData : kV3FrameData,
1763 framer.GetDataFrameMinimumSize());
1767 const char kDescription[] = "Data frame with negative data byte, no FIN";
1768 const unsigned char kV3FrameData[] = { // Also applies for V2.
1769 0x00, 0x00, 0x00, 0x01,
1770 0x00, 0x00, 0x00, 0x01,
1771 0xff
1773 const unsigned char kV4FrameData[] = {
1774 0x00, 0x00, 0x01, 0x00, 0x00,
1775 0x00, 0x00, 0x00, 0x01,
1776 0xff
1778 SpdyDataIR data_ir(1, "\xff");
1779 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1780 if (IsSpdy4()) {
1781 CompareFrame(
1782 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1783 } else {
1784 CompareFrame(
1785 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1790 const char kDescription[] = "'hello' data frame, with FIN";
1791 const unsigned char kV3FrameData[] = { // Also applies for V2.
1792 0x00, 0x00, 0x00, 0x01,
1793 0x01, 0x00, 0x00, 0x05,
1794 'h', 'e', 'l', 'l',
1797 const unsigned char kV4FrameData[] = {
1798 0x00, 0x00, 0x05, 0x00,
1799 0x01, 0x00, 0x00, 0x00,
1800 0x01, 'h', 'e', 'l',
1801 'l', 'o'
1803 SpdyDataIR data_ir(1, "hello");
1804 data_ir.set_fin(true);
1805 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1806 if (IsSpdy4()) {
1807 CompareFrame(
1808 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1809 } else {
1810 CompareFrame(
1811 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1816 const char kDescription[] = "Empty data frame";
1817 const unsigned char kV3FrameData[] = { // Also applies for V2.
1818 0x00, 0x00, 0x00, 0x01,
1819 0x00, 0x00, 0x00, 0x00,
1821 const unsigned char kV4FrameData[] = {
1822 0x00, 0x00, 0x00, 0x00,
1823 0x00, 0x00, 0x00, 0x00,
1824 0x01,
1826 SpdyDataIR data_ir(1, "");
1827 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1828 if (IsSpdy4()) {
1829 CompareFrame(
1830 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1831 } else {
1832 CompareFrame(
1833 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1836 frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
1837 CompareCharArraysWithHexError(
1838 kDescription,
1839 reinterpret_cast<const unsigned char*>(frame->data()),
1840 framer.GetDataFrameMinimumSize(),
1841 IsSpdy4() ? kV4FrameData : kV3FrameData,
1842 framer.GetDataFrameMinimumSize());
1846 const char kDescription[] = "Data frame with max stream ID";
1847 const unsigned char kV3FrameData[] = { // Also applies for V2.
1848 0x7f, 0xff, 0xff, 0xff,
1849 0x01, 0x00, 0x00, 0x05,
1850 'h', 'e', 'l', 'l',
1853 const unsigned char kV4FrameData[] = {
1854 0x00, 0x00, 0x05, 0x00,
1855 0x01, 0x7f, 0xff, 0xff,
1856 0xff, 'h', 'e', 'l',
1857 'l', 'o'
1859 SpdyDataIR data_ir(0x7fffffff, "hello");
1860 data_ir.set_fin(true);
1861 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1862 if (IsSpdy4()) {
1863 CompareFrame(
1864 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
1865 } else {
1866 CompareFrame(
1867 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1871 if (!IsSpdy4()) {
1872 // This test does not apply to SPDY 4 because the max frame size is smaller
1873 // than 4MB.
1874 const char kDescription[] = "Large data frame";
1875 const int kDataSize = 4 * 1024 * 1024; // 4 MB
1876 const string kData(kDataSize, 'A');
1877 const unsigned char kFrameHeader[] = {
1878 0x00, 0x00, 0x00, 0x01,
1879 0x01, 0x40, 0x00, 0x00,
1882 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
1883 scoped_ptr<unsigned char[]> expected_frame_data(
1884 new unsigned char[kFrameSize]);
1885 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
1886 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
1888 SpdyDataIR data_ir(1, kData);
1889 data_ir.set_fin(true);
1890 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
1891 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
1895 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1896 if (!IsSpdy2() && !IsSpdy3()) {
1897 // SYN_STREAM unsupported in SPDY>3
1898 return;
1900 SpdyFramer framer(spdy_version_);
1901 framer.set_enable_compression(false);
1904 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
1906 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
1907 const unsigned char kV2FrameData[] = {
1908 0x80, spdy_version_ch_, 0x00, 0x01,
1909 0x00, 0x00, 0x00, 0x20,
1910 0x00, 0x00, 0x00, 0x01,
1911 0x00, 0x00, 0x00, 0x00,
1912 kPri, 0x00, 0x00, 0x02,
1913 0x00, 0x03, 'b', 'a',
1914 'r', 0x00, 0x03, 'f',
1915 'o', 'o', 0x00, 0x03,
1916 'f', 'o', 'o', 0x00,
1917 0x03, 'b', 'a', 'r'
1919 const unsigned char kV3FrameData[] = {
1920 0x80, spdy_version_ch_, 0x00, 0x01,
1921 0x00, 0x00, 0x00, 0x2a,
1922 0x00, 0x00, 0x00, 0x01,
1923 0x00, 0x00, 0x00, 0x00,
1924 kPri, 0x00, 0x00, 0x00,
1925 0x00, 0x02, 0x00, 0x00,
1926 0x00, 0x03, 'b', 'a',
1927 'r', 0x00, 0x00, 0x00,
1928 0x03, 'f', 'o', 'o',
1929 0x00, 0x00, 0x00, 0x03,
1930 'f', 'o', 'o', 0x00,
1931 0x00, 0x00, 0x03, 'b',
1932 'a', 'r'
1934 SpdySynStreamIR syn_stream(1);
1935 syn_stream.set_priority(framer.GetLowestPriority());
1936 syn_stream.SetHeader("bar", "foo");
1937 syn_stream.SetHeader("foo", "bar");
1938 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1939 if (IsSpdy2()) {
1940 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1941 } else if (IsSpdy3()) {
1942 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1943 } else {
1944 LOG(FATAL) << "Unsupported version in test.";
1949 const char kDescription[] =
1950 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1951 "max stream ID";
1953 const unsigned char kV2FrameData[] = {
1954 0x80, spdy_version_ch_, 0x00, 0x01,
1955 0x01, 0x00, 0x00, 0x1D,
1956 0x7f, 0xff, 0xff, 0xff,
1957 0x7f, 0xff, 0xff, 0xff,
1958 0x00, 0x00, 0x00, 0x02,
1959 0x00, 0x00, 0x00, 0x03,
1960 'f', 'o', 'o', 0x00,
1961 0x03, 'f', 'o', 'o',
1962 0x00, 0x03, 'b', 'a',
1965 const unsigned char kV3FrameData[] = {
1966 0x80, spdy_version_ch_, 0x00, 0x01,
1967 0x01, 0x00, 0x00, 0x27,
1968 0x7f, 0xff, 0xff, 0xff,
1969 0x7f, 0xff, 0xff, 0xff,
1970 0x00, 0x00, 0x00, 0x00,
1971 0x00, 0x02, 0x00, 0x00,
1972 0x00, 0x00, 0x00, 0x00,
1973 0x00, 0x03, 'f', 'o',
1974 'o', 0x00, 0x00, 0x00,
1975 0x03, 'f', 'o', 'o',
1976 0x00, 0x00, 0x00, 0x03,
1977 'b', 'a', 'r'
1979 SpdySynStreamIR syn_stream(0x7fffffff);
1980 syn_stream.set_associated_to_stream_id(0x7fffffff);
1981 syn_stream.set_priority(framer.GetHighestPriority());
1982 syn_stream.set_fin(true);
1983 syn_stream.SetHeader("", "foo");
1984 syn_stream.SetHeader("foo", "bar");
1985 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
1986 if (IsSpdy2()) {
1987 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
1988 } else if (IsSpdy3()) {
1989 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
1990 } else {
1991 LOG(FATAL) << "Unsupported version in test.";
1996 const char kDescription[] =
1997 "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
1998 "max stream ID";
2000 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
2001 const unsigned char kV2FrameData[] = {
2002 0x80, spdy_version_ch_, 0x00, 0x01,
2003 0x01, 0x00, 0x00, 0x1D,
2004 0x7f, 0xff, 0xff, 0xff,
2005 0x7f, 0xff, 0xff, 0xff,
2006 kPri, 0x00, 0x00, 0x02,
2007 0x00, 0x03, 'b', 'a',
2008 'r', 0x00, 0x03, 'f',
2009 'o', 'o', 0x00, 0x03,
2010 'f', 'o', 'o', 0x00,
2011 0x00
2013 const unsigned char kV3FrameData[] = {
2014 0x80, spdy_version_ch_, 0x00, 0x01,
2015 0x01, 0x00, 0x00, 0x27,
2016 0x7f, 0xff, 0xff, 0xff,
2017 0x7f, 0xff, 0xff, 0xff,
2018 kPri, 0x00, 0x00, 0x00,
2019 0x00, 0x02, 0x00, 0x00,
2020 0x00, 0x03, 'b', 'a',
2021 'r', 0x00, 0x00, 0x00,
2022 0x03, 'f', 'o', 'o',
2023 0x00, 0x00, 0x00, 0x03,
2024 'f', 'o', 'o', 0x00,
2025 0x00, 0x00, 0x00
2027 SpdySynStreamIR syn_stream(0x7fffffff);
2028 syn_stream.set_associated_to_stream_id(0x7fffffff);
2029 syn_stream.set_priority(1);
2030 syn_stream.set_fin(true);
2031 syn_stream.SetHeader("bar", "foo");
2032 syn_stream.SetHeader("foo", "");
2033 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2034 if (IsSpdy2()) {
2035 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2036 } else if (IsSpdy3()) {
2037 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2038 } else {
2039 LOG(FATAL) << "Unsupported version in test.";
2044 // TODO(phajdan.jr): Clean up after we no longer need
2045 // to workaround http://crbug.com/139744.
2046 #if !defined(USE_SYSTEM_ZLIB)
2047 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
2048 if (!IsSpdy2() && !IsSpdy3()) {
2049 // SYN_STREAM not supported for SPDY>3
2050 return;
2052 SpdyFramer framer(spdy_version_);
2053 framer.set_enable_compression(true);
2056 const char kDescription[] =
2057 "SYN_STREAM frame, low pri, no FIN";
2058 const SpdyPriority priority = IsSpdy2() ? 2 : 4;
2060 const unsigned char kV2FrameData[] = {
2061 0x80, spdy_version_ch_, 0x00, 0x01,
2062 0x00, 0x00, 0x00, 0x36,
2063 0x00, 0x00, 0x00, 0x01,
2064 0x00, 0x00, 0x00, 0x00,
2065 0x80, 0x00, 0x38, 0xea,
2066 0xdf, 0xa2, 0x51, 0xb2,
2067 0x62, 0x60, 0x62, 0x60,
2068 0x4e, 0x4a, 0x2c, 0x62,
2069 0x60, 0x06, 0x08, 0xa0,
2070 0xb4, 0xfc, 0x7c, 0x80,
2071 0x00, 0x62, 0x60, 0x4e,
2072 0xcb, 0xcf, 0x67, 0x60,
2073 0x06, 0x08, 0xa0, 0xa4,
2074 0xc4, 0x22, 0x80, 0x00,
2075 0x02, 0x00, 0x00, 0x00,
2076 0xff, 0xff,
2078 const unsigned char kV3FrameData[] = {
2079 0x80, spdy_version_ch_, 0x00, 0x01,
2080 0x00, 0x00, 0x00, 0x37,
2081 0x00, 0x00, 0x00, 0x01,
2082 0x00, 0x00, 0x00, 0x00,
2083 0x80, 0x00, 0x38, 0xEA,
2084 0xE3, 0xC6, 0xA7, 0xC2,
2085 0x02, 0xE5, 0x0E, 0x50,
2086 0xC2, 0x4B, 0x4A, 0x04,
2087 0xE5, 0x0B, 0x66, 0x80,
2088 0x00, 0x4A, 0xCB, 0xCF,
2089 0x07, 0x08, 0x20, 0x10,
2090 0x95, 0x96, 0x9F, 0x0F,
2091 0xA2, 0x00, 0x02, 0x28,
2092 0x29, 0xB1, 0x08, 0x20,
2093 0x80, 0x00, 0x00, 0x00,
2094 0x00, 0xFF, 0xFF,
2096 const unsigned char kV2SIMDFrameData[] = {
2097 0x80, spdy_version_ch_, 0x00, 0x01,
2098 0x00, 0x00, 0x00, 0x33,
2099 0x00, 0x00, 0x00, 0x01,
2100 0x00, 0x00, 0x00, 0x00,
2101 0x80, 0x00, 0x38, 0xea,
2102 0xdf, 0xa2, 0x51, 0xb2,
2103 0x62, 0x60, 0x62, 0x60,
2104 0x4e, 0x4a, 0x2c, 0x62,
2105 0x60, 0x06, 0x08, 0xa0,
2106 0xb4, 0xfc, 0x7c, 0x80,
2107 0x00, 0x62, 0x60, 0x06,
2108 0x13, 0x00, 0x01, 0x94,
2109 0x94, 0x58, 0x04, 0x10,
2110 0x40, 0x00, 0x00, 0x00,
2111 0x00, 0xff, 0xff,
2113 const unsigned char kV3SIMDFrameData[] = {
2114 0x80, spdy_version_ch_, 0x00, 0x01,
2115 0x00, 0x00, 0x00, 0x32,
2116 0x00, 0x00, 0x00, 0x01,
2117 0x00, 0x00, 0x00, 0x00,
2118 0x80, 0x00, 0x38, 0xea,
2119 0xe3, 0xc6, 0xa7, 0xc2,
2120 0x02, 0xe5, 0x0e, 0x50,
2121 0xc2, 0x4b, 0x4a, 0x04,
2122 0xe5, 0x0b, 0x66, 0x80,
2123 0x00, 0x4a, 0xcb, 0xcf,
2124 0x07, 0x08, 0x20, 0x24,
2125 0x0a, 0x20, 0x80, 0x92,
2126 0x12, 0x8b, 0x00, 0x02,
2127 0x08, 0x00, 0x00, 0x00,
2128 0xff, 0xff,
2131 SpdySynStreamIR syn_stream(1);
2132 syn_stream.set_priority(priority);
2133 syn_stream.SetHeader("bar", "foo");
2134 syn_stream.SetHeader("foo", "bar");
2135 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
2136 const unsigned char* frame_data =
2137 reinterpret_cast<const unsigned char*>(frame->data());
2138 if (IsSpdy2()) {
2139 // Try comparing with SIMD version, if that fails, do a failing check
2140 // with pretty printing against non-SIMD version
2141 if (memcmp(frame_data,
2142 kV2SIMDFrameData,
2143 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2144 CompareCharArraysWithHexError(kDescription,
2145 frame_data,
2146 frame->size(),
2147 kV2FrameData,
2148 arraysize(kV2FrameData));
2150 } else if (IsSpdy3()) {
2151 if (memcmp(frame_data,
2152 kV3SIMDFrameData,
2153 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2154 CompareCharArraysWithHexError(kDescription,
2155 frame_data,
2156 frame->size(),
2157 kV3FrameData,
2158 arraysize(kV3FrameData));
2160 } else {
2161 LOG(FATAL) << "Unsupported version in test.";
2165 #endif // !defined(USE_SYSTEM_ZLIB)
2167 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
2168 if (spdy_version_ > SPDY3) {
2169 // SYN_REPLY unsupported in SPDY>3
2170 return;
2172 SpdyFramer framer(spdy_version_);
2173 framer.set_enable_compression(false);
2176 const char kDescription[] = "SYN_REPLY frame, no FIN";
2178 const unsigned char kV2FrameData[] = {
2179 0x80, spdy_version_ch_, 0x00, 0x02,
2180 0x00, 0x00, 0x00, 0x1C,
2181 0x00, 0x00, 0x00, 0x01,
2182 0x00, 0x00, 0x00, 0x02,
2183 0x00, 0x03, 'b', 'a',
2184 'r', 0x00, 0x03, 'f',
2185 'o', 'o', 0x00, 0x03,
2186 'f', 'o', 'o', 0x00,
2187 0x03, 'b', 'a', 'r'
2189 const unsigned char kV3FrameData[] = {
2190 0x80, spdy_version_ch_, 0x00, 0x02,
2191 0x00, 0x00, 0x00, 0x24,
2192 0x00, 0x00, 0x00, 0x01,
2193 0x00, 0x00, 0x00, 0x02,
2194 0x00, 0x00, 0x00, 0x03,
2195 'b', 'a', 'r', 0x00,
2196 0x00, 0x00, 0x03, 'f',
2197 'o', 'o', 0x00, 0x00,
2198 0x00, 0x03, 'f', 'o',
2199 'o', 0x00, 0x00, 0x00,
2200 0x03, 'b', 'a', 'r'
2202 SpdySynReplyIR syn_reply(1);
2203 syn_reply.SetHeader("bar", "foo");
2204 syn_reply.SetHeader("foo", "bar");
2205 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2206 if (IsSpdy2()) {
2207 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2208 } else if (IsSpdy3()) {
2209 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2210 } else {
2211 LOG(FATAL) << "Unsupported version in test.";
2216 const char kDescription[] =
2217 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
2219 const unsigned char kV2FrameData[] = {
2220 0x80, spdy_version_ch_, 0x00, 0x02,
2221 0x01, 0x00, 0x00, 0x19,
2222 0x7f, 0xff, 0xff, 0xff,
2223 0x00, 0x00, 0x00, 0x02,
2224 0x00, 0x00, 0x00, 0x03,
2225 'f', 'o', 'o', 0x00,
2226 0x03, 'f', 'o', 'o',
2227 0x00, 0x03, 'b', 'a',
2230 const unsigned char kV3FrameData[] = {
2231 0x80, spdy_version_ch_, 0x00, 0x02,
2232 0x01, 0x00, 0x00, 0x21,
2233 0x7f, 0xff, 0xff, 0xff,
2234 0x00, 0x00, 0x00, 0x02,
2235 0x00, 0x00, 0x00, 0x00,
2236 0x00, 0x00, 0x00, 0x03,
2237 'f', 'o', 'o', 0x00,
2238 0x00, 0x00, 0x03, 'f',
2239 'o', 'o', 0x00, 0x00,
2240 0x00, 0x03, 'b', 'a',
2243 SpdySynReplyIR syn_reply(0x7fffffff);
2244 syn_reply.set_fin(true);
2245 syn_reply.SetHeader("", "foo");
2246 syn_reply.SetHeader("foo", "bar");
2247 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2248 if (IsSpdy2()) {
2249 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2250 } else if (IsSpdy3()) {
2251 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2252 } else {
2253 LOG(FATAL) << "Unsupported version in test.";
2258 const char kDescription[] =
2259 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
2261 const unsigned char kV2FrameData[] = {
2262 0x80, spdy_version_ch_, 0x00, 0x02,
2263 0x01, 0x00, 0x00, 0x19,
2264 0x7f, 0xff, 0xff, 0xff,
2265 0x00, 0x00, 0x00, 0x02,
2266 0x00, 0x03, 'b', 'a',
2267 'r', 0x00, 0x03, 'f',
2268 'o', 'o', 0x00, 0x03,
2269 'f', 'o', 'o', 0x00,
2270 0x00
2272 const unsigned char kV3FrameData[] = {
2273 0x80, spdy_version_ch_, 0x00, 0x02,
2274 0x01, 0x00, 0x00, 0x21,
2275 0x7f, 0xff, 0xff, 0xff,
2276 0x00, 0x00, 0x00, 0x02,
2277 0x00, 0x00, 0x00, 0x03,
2278 'b', 'a', 'r', 0x00,
2279 0x00, 0x00, 0x03, 'f',
2280 'o', 'o', 0x00, 0x00,
2281 0x00, 0x03, 'f', 'o',
2282 'o', 0x00, 0x00, 0x00,
2283 0x00
2285 SpdySynReplyIR syn_reply(0x7fffffff);
2286 syn_reply.set_fin(true);
2287 syn_reply.SetHeader("bar", "foo");
2288 syn_reply.SetHeader("foo", "");
2289 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2290 if (IsSpdy2()) {
2291 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2292 } else if (IsSpdy3()) {
2293 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2294 } else {
2295 LOG(FATAL) << "Unsupported version in test.";
2300 // TODO(phajdan.jr): Clean up after we no longer need
2301 // to workaround http://crbug.com/139744.
2302 #if !defined(USE_SYSTEM_ZLIB)
2303 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
2304 if (spdy_version_ > SPDY3) {
2305 // SYN_REPLY unsupported in SPDY>3
2306 return;
2308 SpdyFramer framer(spdy_version_);
2309 framer.set_enable_compression(true);
2312 const char kDescription[] = "SYN_REPLY frame, no FIN";
2314 const unsigned char kV2FrameData[] = {
2315 0x80, spdy_version_ch_, 0x00, 0x02,
2316 0x00, 0x00, 0x00, 0x32,
2317 0x00, 0x00, 0x00, 0x01,
2318 0x00, 0x00, 0x38, 0xea,
2319 0xdf, 0xa2, 0x51, 0xb2,
2320 0x62, 0x60, 0x62, 0x60,
2321 0x4e, 0x4a, 0x2c, 0x62,
2322 0x60, 0x06, 0x08, 0xa0,
2323 0xb4, 0xfc, 0x7c, 0x80,
2324 0x00, 0x62, 0x60, 0x4e,
2325 0xcb, 0xcf, 0x67, 0x60,
2326 0x06, 0x08, 0xa0, 0xa4,
2327 0xc4, 0x22, 0x80, 0x00,
2328 0x02, 0x00, 0x00, 0x00,
2329 0xff, 0xff,
2331 const unsigned char kV3FrameData[] = {
2332 0x80, spdy_version_ch_, 0x00, 0x02,
2333 0x00, 0x00, 0x00, 0x31,
2334 0x00, 0x00, 0x00, 0x01,
2335 0x38, 0xea, 0xe3, 0xc6,
2336 0xa7, 0xc2, 0x02, 0xe5,
2337 0x0e, 0x50, 0xc2, 0x4b,
2338 0x4a, 0x04, 0xe5, 0x0b,
2339 0x66, 0x80, 0x00, 0x4a,
2340 0xcb, 0xcf, 0x07, 0x08,
2341 0x20, 0x10, 0x95, 0x96,
2342 0x9f, 0x0f, 0xa2, 0x00,
2343 0x02, 0x28, 0x29, 0xb1,
2344 0x08, 0x20, 0x80, 0x00,
2345 0x00, 0x00, 0x00, 0xff,
2346 0xff,
2348 const unsigned char kV2SIMDFrameData[] = {
2349 0x80, spdy_version_ch_, 0x00, 0x02,
2350 0x00, 0x00, 0x00, 0x2f,
2351 0x00, 0x00, 0x00, 0x01,
2352 0x00, 0x00, 0x38, 0xea,
2353 0xdf, 0xa2, 0x51, 0xb2,
2354 0x62, 0x60, 0x62, 0x60,
2355 0x4e, 0x4a, 0x2c, 0x62,
2356 0x60, 0x06, 0x08, 0xa0,
2357 0xb4, 0xfc, 0x7c, 0x80,
2358 0x00, 0x62, 0x60, 0x06,
2359 0x13, 0x00, 0x01, 0x94,
2360 0x94, 0x58, 0x04, 0x10,
2361 0x40, 0x00, 0x00, 0x00,
2362 0x00, 0xff, 0xff,
2364 const unsigned char kV3SIMDFrameData[] = {
2365 0x80, spdy_version_ch_, 0x00, 0x02,
2366 0x00, 0x00, 0x00, 0x2c,
2367 0x00, 0x00, 0x00, 0x01,
2368 0x38, 0xea, 0xe3, 0xc6,
2369 0xa7, 0xc2, 0x02, 0xe5,
2370 0x0e, 0x50, 0xc2, 0x4b,
2371 0x4a, 0x04, 0xe5, 0x0b,
2372 0x66, 0x80, 0x00, 0x4a,
2373 0xcb, 0xcf, 0x07, 0x08,
2374 0x20, 0x24, 0x0a, 0x20,
2375 0x80, 0x92, 0x12, 0x8b,
2376 0x00, 0x02, 0x08, 0x00,
2377 0x00, 0x00, 0xff, 0xff,
2380 SpdySynReplyIR syn_reply(1);
2381 syn_reply.SetHeader("bar", "foo");
2382 syn_reply.SetHeader("foo", "bar");
2383 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
2384 const unsigned char* frame_data =
2385 reinterpret_cast<const unsigned char*>(frame->data());
2386 if (IsSpdy2()) {
2387 // Try comparing with SIMD version, if that fails, do a failing check
2388 // with pretty printing against non-SIMD version
2389 if (memcmp(frame_data,
2390 kV2SIMDFrameData,
2391 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
2392 CompareCharArraysWithHexError(kDescription,
2393 frame_data,
2394 frame->size(),
2395 kV2FrameData,
2396 arraysize(kV2FrameData));
2398 } else if (IsSpdy3()) {
2399 if (memcmp(frame_data,
2400 kV3SIMDFrameData,
2401 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
2402 CompareCharArraysWithHexError(kDescription,
2403 frame_data,
2404 frame->size(),
2405 kV3FrameData,
2406 arraysize(kV3FrameData));
2408 } else {
2409 LOG(FATAL) << "Unsupported version in test.";
2413 #endif // !defined(USE_SYSTEM_ZLIB)
2415 TEST_P(SpdyFramerTest, CreateRstStream) {
2416 SpdyFramer framer(spdy_version_);
2419 const char kDescription[] = "RST_STREAM frame";
2420 const unsigned char kV3FrameData[] = { // Also applies for V2.
2421 0x80, spdy_version_ch_, 0x00, 0x03,
2422 0x00, 0x00, 0x00, 0x08,
2423 0x00, 0x00, 0x00, 0x01,
2424 0x00, 0x00, 0x00, 0x01,
2426 const unsigned char kV4FrameData[] = {
2427 0x00, 0x00, 0x07, 0x03,
2428 0x00, 0x00, 0x00, 0x00,
2429 0x01, 0x00, 0x00, 0x00,
2430 0x01, 0x52, 0x53, 0x54
2432 SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
2433 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2434 if (IsSpdy4()) {
2435 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2436 } else {
2437 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2442 const char kDescription[] = "RST_STREAM frame with max stream ID";
2443 const unsigned char kV3FrameData[] = { // Also applies for V2.
2444 0x80, spdy_version_ch_, 0x00, 0x03,
2445 0x00, 0x00, 0x00, 0x08,
2446 0x7f, 0xff, 0xff, 0xff,
2447 0x00, 0x00, 0x00, 0x01,
2449 const unsigned char kV4FrameData[] = {
2450 0x00, 0x00, 0x04, 0x03,
2451 0x00, 0x7f, 0xff, 0xff,
2452 0xff, 0x00, 0x00, 0x00,
2453 0x01,
2455 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2456 RST_STREAM_PROTOCOL_ERROR,
2457 "");
2458 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2459 if (IsSpdy4()) {
2460 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2461 } else {
2462 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2467 const char kDescription[] = "RST_STREAM frame with max status code";
2468 const unsigned char kV3FrameData[] = { // Also applies for V2.
2469 0x80, spdy_version_ch_, 0x00, 0x03,
2470 0x00, 0x00, 0x00, 0x08,
2471 0x7f, 0xff, 0xff, 0xff,
2472 0x00, 0x00, 0x00, 0x06,
2474 const unsigned char kV4FrameData[] = {
2475 0x00, 0x00, 0x04, 0x03,
2476 0x00, 0x7f, 0xff, 0xff,
2477 0xff, 0x00, 0x00, 0x00,
2478 0x02,
2480 SpdyRstStreamIR rst_stream(0x7FFFFFFF,
2481 RST_STREAM_INTERNAL_ERROR,
2482 "");
2483 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
2484 if (IsSpdy4()) {
2485 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2486 } else {
2487 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2492 TEST_P(SpdyFramerTest, CreateSettings) {
2493 SpdyFramer framer(spdy_version_);
2496 const char kDescription[] = "Network byte order SETTINGS frame";
2498 const unsigned char kV2FrameData[] = {
2499 0x80, spdy_version_ch_, 0x00, 0x04,
2500 0x00, 0x00, 0x00, 0x0c,
2501 0x00, 0x00, 0x00, 0x01,
2502 0x07, 0x00, 0x00, 0x01,
2503 0x0a, 0x0b, 0x0c, 0x0d,
2505 const unsigned char kV3FrameData[] = {
2506 0x80, spdy_version_ch_, 0x00, 0x04,
2507 0x00, 0x00, 0x00, 0x0c,
2508 0x00, 0x00, 0x00, 0x01,
2509 0x01, 0x00, 0x00, 0x07,
2510 0x0a, 0x0b, 0x0c, 0x0d,
2512 const unsigned char kV4FrameData[] = {
2513 0x00, 0x00, 0x06, 0x04,
2514 0x00, 0x00, 0x00, 0x00,
2515 0x00, 0x00, 0x04, 0x0a,
2516 0x0b, 0x0c, 0x0d,
2519 uint32 kValue = 0x0a0b0c0d;
2520 SpdySettingsIR settings_ir;
2522 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
2523 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
2524 settings_ir.AddSetting(kId,
2525 kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
2526 kFlags & SETTINGS_FLAG_PERSISTED,
2527 kValue);
2529 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2530 if (IsSpdy2()) {
2531 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2532 } else if (IsSpdy3()) {
2533 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2534 } else {
2535 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2540 const char kDescription[] = "Basic SETTINGS frame";
2542 const unsigned char kV2FrameData[] = {
2543 0x80, spdy_version_ch_, 0x00, 0x04,
2544 0x00, 0x00, 0x00, 0x24,
2545 0x00, 0x00, 0x00, 0x04,
2546 0x01, 0x00, 0x00, 0x00, // 1st Setting
2547 0x00, 0x00, 0x00, 0x05,
2548 0x02, 0x00, 0x00, 0x00, // 2nd Setting
2549 0x00, 0x00, 0x00, 0x06,
2550 0x03, 0x00, 0x00, 0x00, // 3rd Setting
2551 0x00, 0x00, 0x00, 0x07,
2552 0x04, 0x00, 0x00, 0x00, // 4th Setting
2553 0x00, 0x00, 0x00, 0x08,
2555 const unsigned char kV3FrameData[] = {
2556 0x80, spdy_version_ch_, 0x00, 0x04,
2557 0x00, 0x00, 0x00, 0x24,
2558 0x00, 0x00, 0x00, 0x04,
2559 0x00, 0x00, 0x00, 0x01, // 1st Setting
2560 0x00, 0x00, 0x00, 0x05,
2561 0x00, 0x00, 0x00, 0x02, // 2nd Setting
2562 0x00, 0x00, 0x00, 0x06,
2563 0x00, 0x00, 0x00, 0x03, // 3rd Setting
2564 0x00, 0x00, 0x00, 0x07,
2565 0x00, 0x00, 0x00, 0x04, // 4th Setting
2566 0x00, 0x00, 0x00, 0x08,
2568 // These end up seemingly out of order because of the way that our internal
2569 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
2570 // the wire.
2571 const unsigned char kV4FrameData[] = {
2572 0x00, 0x00, 0x18, 0x04,
2573 0x00, 0x00, 0x00, 0x00,
2574 0x00, 0x00, 0x03, // 3rd Setting
2575 0x00, 0x00, 0x00, 0x07,
2576 0x00, 0x04, // 4th Setting
2577 0x00, 0x00, 0x00, 0x08,
2578 0x00, 0x01, // 1st Setting
2579 0x00, 0x00, 0x00, 0x05,
2580 0x00, 0x02, // 2nd Setting
2581 0x00, 0x00, 0x00, 0x06,
2584 SpdySettingsIR settings_ir;
2585 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
2586 false, // persist
2587 false, // persisted
2589 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
2590 false, // persist
2591 false, // persisted
2593 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
2594 false, // persist
2595 false, // persisted
2597 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
2598 false, // persist
2599 false, // persisted
2601 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2603 if (IsSpdy2()) {
2604 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2605 } else if (IsSpdy3()) {
2606 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2607 } else {
2608 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2613 const char kDescription[] = "Empty SETTINGS frame";
2615 const unsigned char kV3FrameData[] = { // Also applies for V2.
2616 0x80, spdy_version_ch_, 0x00, 0x04,
2617 0x00, 0x00, 0x00, 0x04,
2618 0x00, 0x00, 0x00, 0x00,
2620 const unsigned char kV4FrameData[] = {
2621 0x00, 0x00, 0x00, 0x04,
2622 0x00, 0x00, 0x00, 0x00,
2623 0x00,
2625 SpdySettingsIR settings_ir;
2626 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
2627 if (IsSpdy4()) {
2628 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2629 } else {
2630 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2635 TEST_P(SpdyFramerTest, CreatePingFrame) {
2636 SpdyFramer framer(spdy_version_);
2639 const char kDescription[] = "PING frame";
2640 const unsigned char kV3FrameData[] = { // Also applies for V2.
2641 0x80, spdy_version_ch_, 0x00, 0x06,
2642 0x00, 0x00, 0x00, 0x04,
2643 0x12, 0x34, 0x56, 0x78,
2645 const unsigned char kV4FrameData[] = {
2646 0x00, 0x00, 0x08, 0x06,
2647 0x00, 0x00, 0x00, 0x00,
2648 0x00, 0x12, 0x34, 0x56,
2649 0x78, 0x9a, 0xbc, 0xde,
2650 0xff,
2652 const unsigned char kV4FrameDataWithAck[] = {
2653 0x00, 0x00, 0x08, 0x06,
2654 0x01, 0x00, 0x00, 0x00,
2655 0x00, 0x12, 0x34, 0x56,
2656 0x78, 0x9a, 0xbc, 0xde,
2657 0xff,
2659 scoped_ptr<SpdyFrame> frame;
2660 if (IsSpdy4()) {
2661 const SpdyPingId kPingId = 0x123456789abcdeffULL;
2662 SpdyPingIR ping_ir(kPingId);
2663 // Tests SpdyPingIR when the ping is not an ack.
2664 ASSERT_FALSE(ping_ir.is_ack());
2665 frame.reset(framer.SerializePing(ping_ir));
2666 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2668 // Tests SpdyPingIR when the ping is an ack.
2669 ping_ir.set_is_ack(true);
2670 frame.reset(framer.SerializePing(ping_ir));
2671 CompareFrame(kDescription, *frame,
2672 kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
2674 } else {
2675 frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
2676 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2681 TEST_P(SpdyFramerTest, CreateGoAway) {
2682 SpdyFramer framer(spdy_version_);
2685 const char kDescription[] = "GOAWAY frame";
2686 const unsigned char kV2FrameData[] = {
2687 0x80, spdy_version_ch_, 0x00, 0x07,
2688 0x00, 0x00, 0x00, 0x04,
2689 0x00, 0x00, 0x00, 0x00, // Stream Id
2691 const unsigned char kV3FrameData[] = {
2692 0x80, spdy_version_ch_, 0x00, 0x07,
2693 0x00, 0x00, 0x00, 0x08,
2694 0x00, 0x00, 0x00, 0x00, // Stream Id
2695 0x00, 0x00, 0x00, 0x00, // Status
2697 const unsigned char kV4FrameData[] = {
2698 0x00, 0x00, 0x0a, 0x07,
2699 0x00, 0x00, 0x00, 0x00,
2700 0x00, 0x00, 0x00, 0x00, // Stream id
2701 0x00, 0x00, 0x00, 0x00, // Status
2702 0x00, 0x47, 0x41, // Opaque Description
2704 SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
2705 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2706 if (IsSpdy2()) {
2707 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2708 } else if (IsSpdy3()) {
2709 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2710 } else {
2711 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2716 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2717 const unsigned char kV2FrameData[] = {
2718 0x80, spdy_version_ch_, 0x00, 0x07,
2719 0x00, 0x00, 0x00, 0x04,
2720 0x7f, 0xff, 0xff, 0xff, // Stream Id
2722 const unsigned char kV3FrameData[] = {
2723 0x80, spdy_version_ch_, 0x00, 0x07,
2724 0x00, 0x00, 0x00, 0x08,
2725 0x7f, 0xff, 0xff, 0xff, // Stream Id
2726 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
2728 const unsigned char kV4FrameData[] = {
2729 0x00, 0x00, 0x0a, 0x07,
2730 0x00, 0x00, 0x00, 0x00,
2731 0x00, 0x7f, 0xff, 0xff, // Stream Id
2732 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
2733 0x02, 0x47, 0x41, // Opaque Description
2735 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
2736 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
2737 if (IsSpdy2()) {
2738 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2739 } else if (IsSpdy3()) {
2740 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2741 } else {
2742 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2747 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2748 SpdyFramer framer(spdy_version_);
2749 framer.set_enable_compression(false);
2752 const char kDescription[] = "HEADERS frame, no FIN";
2754 const unsigned char kV2FrameData[] = {
2755 0x80, spdy_version_ch_, 0x00, 0x08,
2756 0x00, 0x00, 0x00, 0x1C,
2757 0x00, 0x00, 0x00, 0x01,
2758 0x00, 0x00, 0x00, 0x02,
2759 0x00, 0x03, 'b', 'a',
2760 'r', 0x00, 0x03, 'f',
2761 'o', 'o', 0x00, 0x03,
2762 'f', 'o', 'o', 0x00,
2763 0x03, 'b', 'a', 'r'
2765 const unsigned char kV3FrameData[] = {
2766 0x80, spdy_version_ch_, 0x00, 0x08,
2767 0x00, 0x00, 0x00, 0x24,
2768 0x00, 0x00, 0x00, 0x01,
2769 0x00, 0x00, 0x00, 0x02,
2770 0x00, 0x00, 0x00, 0x03,
2771 'b', 'a', 'r', 0x00,
2772 0x00, 0x00, 0x03, 'f',
2773 'o', 'o', 0x00, 0x00,
2774 0x00, 0x03, 'f', 'o',
2775 'o', 0x00, 0x00, 0x00,
2776 0x03, 'b', 'a', 'r'
2778 const unsigned char kV4FrameData[] = {
2779 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
2780 0x04, 0x00, 0x00, 0x00, // Stream 1
2781 0x01, 0x00, 0x03, 0x62, // @.ba
2782 0x61, 0x72, 0x03, 0x66, // r.fo
2783 0x6f, 0x6f, 0x00, 0x03, // o@.f
2784 0x66, 0x6f, 0x6f, 0x03, // oo.b
2785 0x62, 0x61, 0x72, // ar
2787 SpdyHeadersIR headers_ir(1);
2788 headers_ir.SetHeader("bar", "foo");
2789 headers_ir.SetHeader("foo", "bar");
2790 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2791 if (IsSpdy2()) {
2792 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2793 } else if (IsSpdy3()) {
2794 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2795 } else {
2796 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2801 const char kDescription[] =
2802 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2804 const unsigned char kV2FrameData[] = {
2805 0x80, spdy_version_ch_, 0x00, 0x08,
2806 0x01, 0x00, 0x00, 0x19,
2807 0x7f, 0xff, 0xff, 0xff,
2808 0x00, 0x00, 0x00, 0x02,
2809 0x00, 0x00, 0x00, 0x03,
2810 'f', 'o', 'o', 0x00,
2811 0x03, 'f', 'o', 'o',
2812 0x00, 0x03, 'b', 'a',
2815 const unsigned char kV3FrameData[] = {
2816 0x80, spdy_version_ch_, 0x00, 0x08,
2817 0x01, 0x00, 0x00, 0x21,
2818 0x7f, 0xff, 0xff, 0xff,
2819 0x00, 0x00, 0x00, 0x02,
2820 0x00, 0x00, 0x00, 0x00,
2821 0x00, 0x00, 0x00, 0x03,
2822 'f', 'o', 'o', 0x00,
2823 0x00, 0x00, 0x03, 'f',
2824 'o', 'o', 0x00, 0x00,
2825 0x00, 0x03, 'b', 'a',
2828 const unsigned char kV4FrameData[] = {
2829 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2830 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2831 0xff, 0x00, 0x00, 0x03, // @..
2832 0x66, 0x6f, 0x6f, 0x00, // foo@
2833 0x03, 0x66, 0x6f, 0x6f, // .foo
2834 0x03, 0x62, 0x61, 0x72, // .bar
2836 SpdyHeadersIR headers_ir(0x7fffffff);
2837 headers_ir.set_fin(true);
2838 headers_ir.SetHeader("", "foo");
2839 headers_ir.SetHeader("foo", "bar");
2840 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2841 if (IsSpdy2()) {
2842 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2843 } else if (IsSpdy3()) {
2844 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2845 } else {
2846 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2851 const char kDescription[] =
2852 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2854 const unsigned char kV2FrameData[] = {
2855 0x80, spdy_version_ch_, 0x00, 0x08,
2856 0x01, 0x00, 0x00, 0x19,
2857 0x7f, 0xff, 0xff, 0xff,
2858 0x00, 0x00, 0x00, 0x02,
2859 0x00, 0x03, 'b', 'a',
2860 'r', 0x00, 0x03, 'f',
2861 'o', 'o', 0x00, 0x03,
2862 'f', 'o', 'o', 0x00,
2863 0x00
2865 const unsigned char kV3FrameData[] = {
2866 0x80, spdy_version_ch_, 0x00, 0x08,
2867 0x01, 0x00, 0x00, 0x21,
2868 0x7f, 0xff, 0xff, 0xff,
2869 0x00, 0x00, 0x00, 0x02,
2870 0x00, 0x00, 0x00, 0x03,
2871 'b', 'a', 'r', 0x00,
2872 0x00, 0x00, 0x03, 'f',
2873 'o', 'o', 0x00, 0x00,
2874 0x00, 0x03, 'f', 'o',
2875 'o', 0x00, 0x00, 0x00,
2876 0x00
2878 const unsigned char kV4FrameData[] = {
2879 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
2880 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2881 0xff, 0x00, 0x03, 0x62, // @.b
2882 0x61, 0x72, 0x03, 0x66, // ar.f
2883 0x6f, 0x6f, 0x00, 0x03, // oo@.
2884 0x66, 0x6f, 0x6f, 0x00, // foo.
2886 SpdyHeadersIR headers_ir(0x7fffffff);
2887 headers_ir.set_fin(true);
2888 headers_ir.SetHeader("bar", "foo");
2889 headers_ir.SetHeader("foo", "");
2890 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2891 if (IsSpdy2()) {
2892 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
2893 } else if (IsSpdy3()) {
2894 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
2895 } else {
2896 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2901 const char kDescription[] =
2902 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2904 const unsigned char kV4FrameData[] = {
2905 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
2906 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
2907 0xff, 0x00, 0x00, 0x00, // parent stream
2908 0x00, 0xdb, // weight
2909 0x00, 0x03, 0x62, 0x61, // @.ba
2910 0x72, 0x03, 0x66, 0x6f, // r.fo
2911 0x6f, 0x00, 0x03, 0x66, // o@.f
2912 0x6f, 0x6f, 0x00, // oo.
2914 SpdyHeadersIR headers_ir(0x7fffffff);
2915 headers_ir.set_fin(true);
2916 headers_ir.set_priority(1);
2917 headers_ir.set_has_priority(true);
2918 headers_ir.SetHeader("bar", "foo");
2919 headers_ir.SetHeader("foo", "");
2920 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2921 if (IsSpdy2() || IsSpdy3()) {
2922 // HEADERS with priority not supported.
2923 } else {
2924 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2929 const char kDescription[] =
2930 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2932 const unsigned char kV4FrameData[] = {
2933 0x00, 0x00, 0x15, 0x01, // Headers
2934 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
2935 // 0x7fffffff
2936 0xff, 0x05, 0x00, 0x00, // Pad length field
2937 0x03, 0x66, 0x6f, 0x6f, // .foo
2938 0x00, 0x03, 0x66, 0x6f, // @.fo
2939 0x6f, 0x03, 0x62, 0x61, // o.ba
2940 0x72, // r
2941 // Padding payload
2942 0x00, 0x00, 0x00, 0x00, 0x00,
2944 SpdyHeadersIR headers_ir(0x7fffffff);
2945 headers_ir.set_fin(true);
2946 headers_ir.SetHeader("", "foo");
2947 headers_ir.SetHeader("foo", "bar");
2948 headers_ir.set_padding_len(6);
2949 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
2950 if (IsSpdy2() || IsSpdy3()) {
2951 // Padding is not supported.
2952 } else {
2953 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
2958 // TODO(phajdan.jr): Clean up after we no longer need
2959 // to workaround http://crbug.com/139744.
2960 #if !defined(USE_SYSTEM_ZLIB)
2961 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
2962 SpdyFramer framer(spdy_version_);
2963 framer.set_enable_compression(true);
2966 const char kDescription[] = "HEADERS frame, no FIN";
2968 const unsigned char kV2FrameData[] = {
2969 0x80, spdy_version_ch_, 0x00, 0x08,
2970 0x00, 0x00, 0x00, 0x32,
2971 0x00, 0x00, 0x00, 0x01,
2972 0x00, 0x00, 0x38, 0xea,
2973 0xdf, 0xa2, 0x51, 0xb2,
2974 0x62, 0x60, 0x62, 0x60,
2975 0x4e, 0x4a, 0x2c, 0x62,
2976 0x60, 0x06, 0x08, 0xa0,
2977 0xb4, 0xfc, 0x7c, 0x80,
2978 0x00, 0x62, 0x60, 0x4e,
2979 0xcb, 0xcf, 0x67, 0x60,
2980 0x06, 0x08, 0xa0, 0xa4,
2981 0xc4, 0x22, 0x80, 0x00,
2982 0x02, 0x00, 0x00, 0x00,
2983 0xff, 0xff,
2985 const unsigned char kV3FrameData[] = {
2986 0x80, spdy_version_ch_, 0x00, 0x08,
2987 0x00, 0x00, 0x00, 0x31,
2988 0x00, 0x00, 0x00, 0x01,
2989 0x38, 0xea, 0xe3, 0xc6,
2990 0xa7, 0xc2, 0x02, 0xe5,
2991 0x0e, 0x50, 0xc2, 0x4b,
2992 0x4a, 0x04, 0xe5, 0x0b,
2993 0x66, 0x80, 0x00, 0x4a,
2994 0xcb, 0xcf, 0x07, 0x08,
2995 0x20, 0x10, 0x95, 0x96,
2996 0x9f, 0x0f, 0xa2, 0x00,
2997 0x02, 0x28, 0x29, 0xb1,
2998 0x08, 0x20, 0x80, 0x00,
2999 0x00, 0x00, 0x00, 0xff,
3000 0xff,
3002 const unsigned char kV2SIMDFrameData[] = {
3003 0x80, spdy_version_ch_, 0x00, 0x08,
3004 0x00, 0x00, 0x00, 0x2f,
3005 0x00, 0x00, 0x00, 0x01,
3006 0x00, 0x00, 0x38, 0xea,
3007 0xdf, 0xa2, 0x51, 0xb2,
3008 0x62, 0x60, 0x62, 0x60,
3009 0x4e, 0x4a, 0x2c, 0x62,
3010 0x60, 0x06, 0x08, 0xa0,
3011 0xb4, 0xfc, 0x7c, 0x80,
3012 0x00, 0x62, 0x60, 0x06,
3013 0x13, 0x00, 0x01, 0x94,
3014 0x94, 0x58, 0x04, 0x10,
3015 0x40, 0x00, 0x00, 0x00,
3016 0x00, 0xff, 0xff,
3018 const unsigned char kV3SIMDFrameData[] = {
3019 0x80, spdy_version_ch_, 0x00, 0x08,
3020 0x00, 0x00, 0x00, 0x2c,
3021 0x00, 0x00, 0x00, 0x01,
3022 0x38, 0xea, 0xe3, 0xc6,
3023 0xa7, 0xc2, 0x02, 0xe5,
3024 0x0e, 0x50, 0xc2, 0x4b,
3025 0x4a, 0x04, 0xe5, 0x0b,
3026 0x66, 0x80, 0x00, 0x4a,
3027 0xcb, 0xcf, 0x07, 0x08,
3028 0x20, 0x24, 0x0a, 0x20,
3029 0x80, 0x92, 0x12, 0x8b,
3030 0x00, 0x02, 0x08, 0x00,
3031 0x00, 0x00, 0xff, 0xff,
3034 SpdyHeadersIR headers_ir(1);
3035 headers_ir.SetHeader("bar", "foo");
3036 headers_ir.SetHeader("foo", "bar");
3037 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
3038 const unsigned char* frame_data =
3039 reinterpret_cast<const unsigned char*>(frame->data());
3040 if (IsSpdy2()) {
3041 // Try comparing with SIMD version, if that fails, do a failing check
3042 // with pretty printing against non-SIMD version
3043 if (memcmp(frame_data,
3044 kV2SIMDFrameData,
3045 std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
3046 CompareCharArraysWithHexError(kDescription,
3047 frame_data,
3048 frame->size(),
3049 kV2FrameData,
3050 arraysize(kV2FrameData));
3052 } else if (IsSpdy3()) {
3053 if (memcmp(frame_data,
3054 kV3SIMDFrameData,
3055 std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
3056 CompareCharArraysWithHexError(kDescription,
3057 frame_data,
3058 frame->size(),
3059 kV3FrameData,
3060 arraysize(kV3FrameData));
3062 } else {
3063 // Deflate compression doesn't apply to HPACK.
3067 #endif // !defined(USE_SYSTEM_ZLIB)
3069 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
3070 SpdyFramer framer(spdy_version_);
3073 const char kDescription[] = "WINDOW_UPDATE frame";
3074 const unsigned char kV3FrameData[] = { // Also applies for V2.
3075 0x80, spdy_version_ch_, 0x00, 0x09,
3076 0x00, 0x00, 0x00, 0x08,
3077 0x00, 0x00, 0x00, 0x01,
3078 0x00, 0x00, 0x00, 0x01,
3080 const unsigned char kV4FrameData[] = {
3081 0x00, 0x00, 0x04, 0x08,
3082 0x00, 0x00, 0x00, 0x00,
3083 0x01, 0x00, 0x00, 0x00,
3084 0x01,
3086 scoped_ptr<SpdyFrame> frame(
3087 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
3088 if (IsSpdy4()) {
3089 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3090 } else {
3091 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3096 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
3097 const unsigned char kV3FrameData[] = { // Also applies for V2.
3098 0x80, spdy_version_ch_, 0x00, 0x09,
3099 0x00, 0x00, 0x00, 0x08,
3100 0x7f, 0xff, 0xff, 0xff,
3101 0x00, 0x00, 0x00, 0x01,
3103 const unsigned char kV4FrameData[] = {
3104 0x00, 0x00, 0x04, 0x08,
3105 0x00, 0x7f, 0xff, 0xff,
3106 0xff, 0x00, 0x00, 0x00,
3107 0x01,
3109 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3110 SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
3111 if (IsSpdy4()) {
3112 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3113 } else {
3114 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3119 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
3120 const unsigned char kV3FrameData[] = { // Also applies for V2.
3121 0x80, spdy_version_ch_, 0x00, 0x09,
3122 0x00, 0x00, 0x00, 0x08,
3123 0x00, 0x00, 0x00, 0x01,
3124 0x7f, 0xff, 0xff, 0xff,
3126 const unsigned char kV4FrameData[] = {
3127 0x00, 0x00, 0x04, 0x08,
3128 0x00, 0x00, 0x00, 0x00,
3129 0x01, 0x7f, 0xff, 0xff,
3130 0xff,
3132 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
3133 SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
3134 if (IsSpdy4()) {
3135 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
3136 } else {
3137 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
3142 TEST_P(SpdyFramerTest, SerializeBlocked) {
3143 if (spdy_version_ <= SPDY3) {
3144 return;
3147 SpdyFramer framer(spdy_version_);
3149 const char kDescription[] = "BLOCKED frame";
3150 const unsigned char kType = static_cast<unsigned char>(
3151 SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
3152 const unsigned char kFrameData[] = {
3153 0x00, 0x00, 0x00, kType, 0x00,
3154 0x00, 0x00, 0x00, 0x00,
3156 SpdyBlockedIR blocked_ir(0);
3157 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
3158 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3161 TEST_P(SpdyFramerTest, CreateBlocked) {
3162 if (spdy_version_ <= SPDY3) {
3163 return;
3166 SpdyFramer framer(spdy_version_);
3168 const char kDescription[] = "BLOCKED frame";
3169 const SpdyStreamId kStreamId = 3;
3171 scoped_ptr<SpdySerializedFrame> frame_serialized(
3172 framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
3173 SpdyBlockedIR blocked_ir(kStreamId);
3174 scoped_ptr<SpdySerializedFrame> frame_created(
3175 framer.SerializeFrame(blocked_ir));
3177 CompareFrames(kDescription, *frame_serialized, *frame_created);
3180 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
3181 if (spdy_version_ <= SPDY3) {
3182 return;
3186 // Test framing PUSH_PROMISE without padding.
3187 SpdyFramer framer(spdy_version_);
3188 framer.set_enable_compression(false);
3189 const char kDescription[] = "PUSH_PROMISE frame without padding";
3191 const unsigned char kFrameData[] = {
3192 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
3193 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3194 0x2a, 0x00, 0x00, 0x00, // Stream 42
3195 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
3196 0x61, 0x72, 0x03, 0x66, // ar.f
3197 0x6f, 0x6f, 0x00, 0x03, // oo@.
3198 0x66, 0x6f, 0x6f, 0x03, // foo.
3199 0x62, 0x61, 0x72, // bar
3202 SpdyPushPromiseIR push_promise(42, 57);
3203 push_promise.SetHeader("bar", "foo");
3204 push_promise.SetHeader("foo", "bar");
3205 scoped_ptr<SpdySerializedFrame> frame(
3206 framer.SerializePushPromise(push_promise));
3207 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3211 // Test framing PUSH_PROMISE with one byte of padding.
3212 SpdyFramer framer(spdy_version_);
3213 framer.set_enable_compression(false);
3214 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
3216 const unsigned char kFrameData[] = {
3217 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3218 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3219 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
3220 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3221 0x62, 0x61, 0x72, 0x03, // bar.
3222 0x66, 0x6f, 0x6f, 0x00, // foo@
3223 0x03, 0x66, 0x6f, 0x6f, // .foo
3224 0x03, 0x62, 0x61, 0x72, // .bar
3227 SpdyPushPromiseIR push_promise(42, 57);
3228 push_promise.set_padding_len(1);
3229 push_promise.SetHeader("bar", "foo");
3230 push_promise.SetHeader("foo", "bar");
3231 scoped_ptr<SpdySerializedFrame> frame(
3232 framer.SerializePushPromise(push_promise));
3233 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3237 // Test framing PUSH_PROMISE with 177 bytes of padding.
3238 SpdyFramer framer(spdy_version_);
3239 framer.set_enable_compression(false);
3240 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
3242 const unsigned char kFrameData[] = {
3243 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
3244 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
3245 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
3246 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3247 0x62, 0x61, 0x72, 0x03, // bar.
3248 0x66, 0x6f, 0x6f, 0x00, // foo@
3249 0x03, 0x66, 0x6f, 0x6f, // .foo
3250 0x03, 0x62, 0x61, 0x72, // .bar
3251 // Padding of 176 0x00(s).
3252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3269 SpdyPushPromiseIR push_promise(42, 57);
3270 push_promise.set_padding_len(177);
3271 push_promise.SetHeader("bar", "foo");
3272 push_promise.SetHeader("foo", "bar");
3273 scoped_ptr<SpdySerializedFrame> frame(
3274 framer.SerializePushPromise(push_promise));
3275 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3279 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
3280 if (spdy_version_ <= SPDY3) {
3281 return;
3284 SpdyFramer framer(spdy_version_);
3285 // Test case from https://crbug.com/464748.
3286 EXPECT_EQ(1u,
3287 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2039));
3288 EXPECT_EQ(2u,
3289 SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2040));
3292 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
3293 if (spdy_version_ <= SPDY3) {
3294 return;
3297 SpdyFramer framer(spdy_version_);
3298 framer.set_enable_compression(false);
3299 const char kDescription[] = "CONTINUATION frame";
3301 const unsigned char kFrameData[] = {
3302 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3303 0x04, 0x00, 0x00, 0x00, // end_headers = true
3304 0x2a, 0x00, 0x03, 0x62, // Stream 42, @.b
3305 0x61, 0x72, 0x03, 0x66, // ar.f
3306 0x6f, 0x6f, 0x00, 0x03, // oo@.
3307 0x66, 0x6f, 0x6f, 0x03, // foo.
3308 0x62, 0x61, 0x72, // bar
3311 SpdyContinuationIR continuation(42);
3312 continuation.SetHeader("bar", "foo");
3313 continuation.SetHeader("foo", "bar");
3314 continuation.set_end_headers(true);
3315 scoped_ptr<SpdySerializedFrame> frame(
3316 framer.SerializeContinuation(continuation));
3317 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3320 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
3321 if (spdy_version_ <= SPDY3) {
3322 return;
3326 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
3327 // padding, cannot hold all the data payload, which is overflowed to the
3328 // consecutive CONTINUATION frame.
3329 SpdyFramer framer(spdy_version_);
3330 framer.set_enable_compression(false);
3331 const char kDescription[] =
3332 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
3334 const unsigned char kPartialPushPromiseFrameData[] = {
3335 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
3336 0x08, 0x00, 0x00, 0x00, // PADDED
3337 0x2a, 0x00, 0x00, 0x00, // Stream 42
3338 0x00, 0x39, 0x00, 0x03, // Promised stream 57
3339 0x78, 0x78, 0x78, 0x7f, // xxx.
3340 0x81, 0x07, 0x78, 0x78, // ..xx
3341 0x78, 0x78, 0x78, 0x78, // xxxx
3342 0x78, 0x78, 0x78, 0x78, // xxxx
3343 0x78, 0x78, 0x78, 0x78, // xxxx
3344 0x78, 0x78, 0x78, 0x78, // xxxx
3345 0x78, 0x78, 0x78, 0x78, // xxxx
3346 0x78, 0x78, 0x78, 0x78, // xxxx
3347 0x78, 0x78, 0x78, 0x78, // xxxx
3348 0x78, 0x78, 0x78, 0x78, // xxxx
3349 0x78, 0x78, 0x78, 0x78, // xxxx
3350 0x78, 0x78, 0x78, 0x78, // xxxx
3351 0x78, 0x78, 0x78, 0x78, // xxxx
3352 0x78, 0x78, 0x78, 0x78, // xxxx
3353 0x78, 0x78, 0x78, 0x78, // xxxx
3354 0x78, 0x78, 0x78, 0x78, // xxxx
3355 0x78, 0x78, 0x78, 0x78, // xxxx
3356 0x78, 0x78, 0x78, 0x78, // xxxx
3357 0x78, 0x78, 0x78, 0x78, // xxxx
3358 0x78, 0x78, 0x78, 0x78, // xxxx
3359 0x78, 0x78, 0x78, 0x78, // xxxx
3360 0x78, 0x78, 0x78, 0x78, // xxxx
3361 0x78, 0x78, // xx
3364 const unsigned char kContinuationFrameData[] = {
3365 0x00, 0x00, 0x16, 0x09, // CONTINUATION
3366 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3367 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
3368 0x78, 0x78, 0x78, 0x78, // xxxx
3369 0x78, 0x78, 0x78, 0x78, // xxxx
3370 0x78, 0x78, 0x78, 0x78, // xxxx
3371 0x78, 0x78, 0x78, 0x78, // xxxx
3372 0x78, 0x78,
3375 SpdyPushPromiseIR push_promise(42, 57);
3376 push_promise.set_padding_len(1);
3377 string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
3378 push_promise.SetHeader("xxx", big_value);
3379 scoped_ptr<SpdySerializedFrame> frame(
3380 framer.SerializePushPromise(push_promise));
3382 // The entire frame should look like below:
3383 // Name Length in Byte
3384 // ------------------------------------------- Begin of PUSH_PROMISE frame
3385 // PUSH_PROMISE header 9
3386 // Pad length field 1
3387 // Promised stream 4
3388 // Length field of key 2
3389 // Content of key 3
3390 // Length field of value 3
3391 // Part of big_value 16361
3392 // ------------------------------------------- Begin of CONTINUATION frame
3393 // CONTINUATION header 9
3394 // Remaining of big_value 22
3395 // ------------------------------------------- End
3397 // Length of everything listed above except big_value.
3398 int len_non_data_payload = 31;
3399 EXPECT_EQ(
3400 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
3401 frame->size());
3403 // Partially compare the PUSH_PROMISE frame against the template.
3404 const unsigned char* frame_data =
3405 reinterpret_cast<const unsigned char*>(frame->data());
3406 CompareCharArraysWithHexError(kDescription,
3407 frame_data,
3408 arraysize(kPartialPushPromiseFrameData),
3409 kPartialPushPromiseFrameData,
3410 arraysize(kPartialPushPromiseFrameData));
3412 // Compare the CONTINUATION frame against the template.
3413 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
3414 CompareCharArraysWithHexError(kDescription,
3415 frame_data,
3416 arraysize(kContinuationFrameData),
3417 kContinuationFrameData,
3418 arraysize(kContinuationFrameData));
3422 TEST_P(SpdyFramerTest, CreateAltSvc) {
3423 if (spdy_version_ <= SPDY3) {
3424 return;
3427 SpdyFramer framer(spdy_version_);
3429 const char kDescription[] = "ALTSVC frame";
3430 const char kType = static_cast<unsigned char>(
3431 SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
3432 const unsigned char kFrameData[] = {
3433 0x00, 0x00, 0x1d, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
3434 0x06, 'o', 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd',
3435 '1', '=', '"', 'h', 'o', 's', 't', ':', '4', '4',
3436 '3', '"', ';', ' ', 'm', 'a', '=', '5',
3438 SpdyAltSvcIR altsvc_ir(3);
3439 altsvc_ir.set_max_age(5);
3440 altsvc_ir.set_port(443);
3441 altsvc_ir.set_protocol_id("pid1");
3442 altsvc_ir.set_host("host");
3443 altsvc_ir.set_origin("origin");
3444 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
3445 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3448 TEST_P(SpdyFramerTest, CreatePriority) {
3449 if (spdy_version_ <= SPDY3) {
3450 return;
3453 SpdyFramer framer(spdy_version_);
3455 const char kDescription[] = "PRIORITY frame";
3456 const unsigned char kType = static_cast<unsigned char>(
3457 SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
3458 const unsigned char kFrameData[] = {
3459 0x00, 0x00, 0x05, kType, 0x00,
3460 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
3461 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
3462 0x10, // Weight = 16
3464 SpdyPriorityIR priority_ir(2, 1, 16, true);
3465 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
3466 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3467 SpdyPriorityIR priority2(2);
3468 priority2.set_parent_stream_id(1);
3469 priority2.set_weight(16);
3470 priority2.set_exclusive(true);
3471 frame.reset(framer.SerializeFrame(priority2));
3472 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
3475 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
3476 if (spdy_version_ > SPDY3) {
3477 // SYN_STREAM not supported in SPDY>3
3478 return;
3480 SpdyFramer framer(spdy_version_);
3481 SpdySynStreamIR syn_stream(1);
3482 syn_stream.set_priority(1);
3483 syn_stream.SetHeader("aa", "vv");
3484 syn_stream.SetHeader("bb", "ww");
3485 SpdyHeaderBlock headers = syn_stream.name_value_block();
3486 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3487 EXPECT_TRUE(control_frame.get() != NULL);
3488 TestSpdyVisitor visitor(spdy_version_);
3489 visitor.use_compression_ = true;
3490 visitor.SimulateInFramer(
3491 reinterpret_cast<unsigned char*>(control_frame->data()),
3492 control_frame->size());
3493 EXPECT_EQ(1, visitor.syn_frame_count_);
3494 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3497 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
3498 if (spdy_version_ > SPDY3) {
3499 return;
3501 SpdyFramer framer(spdy_version_);
3502 SpdySynReplyIR syn_reply(1);
3503 syn_reply.SetHeader("alpha", "beta");
3504 syn_reply.SetHeader("gamma", "delta");
3505 SpdyHeaderBlock headers = syn_reply.name_value_block();
3506 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
3507 EXPECT_TRUE(control_frame.get() != NULL);
3508 TestSpdyVisitor visitor(spdy_version_);
3509 visitor.use_compression_ = true;
3510 visitor.SimulateInFramer(
3511 reinterpret_cast<unsigned char*>(control_frame->data()),
3512 control_frame->size());
3513 if (IsSpdy4()) {
3514 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
3515 EXPECT_EQ(1, visitor.headers_frame_count_);
3516 } else {
3517 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
3518 EXPECT_EQ(0, visitor.headers_frame_count_);
3520 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3523 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
3524 SpdyFramer framer(spdy_version_);
3525 SpdyHeadersIR headers_ir(1);
3526 headers_ir.SetHeader("alpha", "beta");
3527 headers_ir.SetHeader("gamma", "delta");
3528 SpdyHeaderBlock headers = headers_ir.name_value_block();
3529 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3530 EXPECT_TRUE(control_frame.get() != NULL);
3531 TestSpdyVisitor visitor(spdy_version_);
3532 visitor.use_compression_ = true;
3533 visitor.SimulateInFramer(
3534 reinterpret_cast<unsigned char*>(control_frame->data()),
3535 control_frame->size());
3536 EXPECT_EQ(1, visitor.headers_frame_count_);
3537 // control_frame_header_data_count_ depends on the random sequence
3538 // produced by rand(), so adding, removing or running single tests
3539 // alters this value. The best we can do is assert that it happens
3540 // at least twice.
3541 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3542 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3543 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3544 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3547 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
3548 SpdyFramer framer(spdy_version_);
3549 SpdyHeadersIR headers_ir(1);
3550 headers_ir.set_fin(true);
3551 headers_ir.SetHeader("alpha", "beta");
3552 headers_ir.SetHeader("gamma", "delta");
3553 SpdyHeaderBlock headers = headers_ir.name_value_block();
3554 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
3555 EXPECT_TRUE(control_frame.get() != NULL);
3556 TestSpdyVisitor visitor(spdy_version_);
3557 visitor.use_compression_ = true;
3558 visitor.SimulateInFramer(
3559 reinterpret_cast<unsigned char*>(control_frame->data()),
3560 control_frame->size());
3561 EXPECT_EQ(1, visitor.headers_frame_count_);
3562 // control_frame_header_data_count_ depends on the random sequence
3563 // produced by rand(), so adding, removing or running single tests
3564 // alters this value. The best we can do is assert that it happens
3565 // at least twice.
3566 EXPECT_LE(2, visitor.control_frame_header_data_count_);
3567 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3568 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
3569 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
3572 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
3573 if (spdy_version_ > SPDY3) {
3574 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3575 return;
3577 // First find the size of the header value in order to just reach the control
3578 // frame max size.
3579 SpdyFramer framer(spdy_version_);
3580 framer.set_enable_compression(false);
3581 SpdySynStreamIR syn_stream(1);
3582 syn_stream.set_priority(1);
3583 syn_stream.SetHeader("aa", "");
3584 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3585 const size_t kBigValueSize =
3586 TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
3588 // Create a frame at exactly that size.
3589 string big_value(kBigValueSize, 'x');
3590 syn_stream.SetHeader("aa", big_value);
3591 control_frame.reset(framer.SerializeSynStream(syn_stream));
3592 EXPECT_TRUE(control_frame.get() != NULL);
3593 EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
3594 control_frame->size());
3596 TestSpdyVisitor visitor(spdy_version_);
3597 visitor.SimulateInFramer(
3598 reinterpret_cast<unsigned char*>(control_frame->data()),
3599 control_frame->size());
3600 EXPECT_TRUE(visitor.header_buffer_valid_);
3601 EXPECT_EQ(0, visitor.error_count_);
3602 EXPECT_EQ(1, visitor.syn_frame_count_);
3603 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3604 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3605 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
3608 TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
3609 if (spdy_version_ > SPDY3) {
3610 // TODO(jgraettinger): This test setup doesn't work with HPACK.
3611 return;
3613 if (spdy_version_ < SPDY3) {
3614 // Since SPDY/2 uses 16 bit header field lengths, one cannot easily create a
3615 // header frame of maximum size.
3616 return;
3618 // First find the size of the header value in order to just reach the control
3619 // frame max size.
3620 SpdyFramer framer(spdy_version_);
3621 framer.set_enable_compression(false);
3622 SpdySynStreamIR syn_stream(1);
3623 syn_stream.SetHeader("aa", "");
3624 syn_stream.set_priority(1);
3625 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3626 const size_t kBigValueSize =
3627 SpdyConstants::GetFrameMaximumSize(spdy_version_) - control_frame->size();
3629 // Create a frame at exatly that size.
3630 string big_value(kBigValueSize, 'x');
3631 syn_stream.SetHeader("aa", big_value);
3632 // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
3633 // neither support that in Chromium, nor do we use the same DFATAL (see
3634 // SpdyFrameBuilder::WriteFramePrefix()).
3635 control_frame.reset(framer.SerializeSynStream(syn_stream));
3637 EXPECT_TRUE(control_frame.get() != NULL);
3638 EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_),
3639 control_frame->size());
3641 TestSpdyVisitor visitor(spdy_version_);
3642 visitor.SimulateInFramer(
3643 reinterpret_cast<unsigned char*>(control_frame->data()),
3644 control_frame->size());
3645 EXPECT_TRUE(visitor.header_buffer_valid_);
3646 EXPECT_EQ(0, visitor.error_count_);
3647 EXPECT_EQ(1, visitor.syn_frame_count_);
3650 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
3651 if (spdy_version_ <= SPDY3) {
3652 return;
3654 SpdyFramer framer(spdy_version_);
3655 framer.set_enable_compression(false);
3656 SpdyHeadersIR headers(1);
3657 headers.set_padding_len(256);
3659 // Exact payload length will change with HPACK, but this should be long
3660 // enough to cause an overflow.
3661 const size_t kBigValueSize = kControlFrameSizeLimit;
3662 string big_value(kBigValueSize, 'x');
3663 headers.SetHeader("aa", big_value);
3664 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3665 EXPECT_TRUE(control_frame.get() != NULL);
3666 EXPECT_GT(control_frame->size(),
3667 TestSpdyVisitor::sent_control_frame_max_size());
3669 TestSpdyVisitor visitor(spdy_version_);
3670 visitor.SimulateInFramer(
3671 reinterpret_cast<unsigned char*>(control_frame->data()),
3672 control_frame->size());
3673 EXPECT_TRUE(visitor.header_buffer_valid_);
3674 EXPECT_EQ(0, visitor.error_count_);
3675 EXPECT_EQ(1, visitor.headers_frame_count_);
3676 EXPECT_EQ(16, visitor.continuation_count_);
3677 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3680 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3681 if (spdy_version_ <= SPDY3) {
3682 return;
3684 SpdyFramer framer(spdy_version_);
3685 framer.set_enable_compression(false);
3686 SpdyPushPromiseIR push_promise(1, 2);
3687 push_promise.set_padding_len(256);
3689 // Exact payload length will change with HPACK, but this should be long
3690 // enough to cause an overflow.
3691 const size_t kBigValueSize = kControlFrameSizeLimit;
3692 string big_value(kBigValueSize, 'x');
3693 push_promise.SetHeader("aa", big_value);
3694 scoped_ptr<SpdyFrame> control_frame(
3695 framer.SerializePushPromise(push_promise));
3696 EXPECT_TRUE(control_frame.get() != NULL);
3697 EXPECT_GT(control_frame->size(),
3698 TestSpdyVisitor::sent_control_frame_max_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.push_promise_frame_count_);
3707 EXPECT_EQ(16, visitor.continuation_count_);
3708 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
3711 // Check that the framer stops delivering header data chunks once the visitor
3712 // declares it doesn't want any more. This is important to guard against
3713 // "zip bomb" types of attacks.
3714 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3715 const size_t kHeaderBufferChunks = 4;
3716 const size_t kHeaderBufferSize =
3717 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
3718 const size_t kBigValueSize = kHeaderBufferSize * 2;
3719 string big_value(kBigValueSize, 'x');
3720 SpdyFramer framer(spdy_version_);
3721 SpdyHeadersIR headers(1);
3722 headers.set_priority(1);
3723 headers.set_fin(true);
3724 headers.SetHeader("aa", big_value);
3725 scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
3726 EXPECT_TRUE(control_frame.get() != NULL);
3727 TestSpdyVisitor visitor(spdy_version_);
3728 visitor.set_header_buffer_size(kHeaderBufferSize);
3729 visitor.use_compression_ = true;
3730 visitor.SimulateInFramer(
3731 reinterpret_cast<unsigned char*>(control_frame->data()),
3732 control_frame->size());
3733 EXPECT_FALSE(visitor.header_buffer_valid_);
3734 EXPECT_EQ(1, visitor.error_count_);
3735 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
3736 visitor.framer_.error_code())
3737 << SpdyFramer::ErrorCodeToString(framer.error_code());
3739 // The framer should have stoped delivering chunks after the visitor
3740 // signaled "stop" by returning false from OnControlFrameHeaderData().
3742 // control_frame_header_data_count_ depends on the random sequence
3743 // produced by rand(), so adding, removing or running single tests
3744 // alters this value. The best we can do is assert that it happens
3745 // at least kHeaderBufferChunks + 1.
3746 EXPECT_LE(kHeaderBufferChunks + 1,
3747 static_cast<unsigned>(visitor.control_frame_header_data_count_));
3748 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3750 // The framer should not have sent half-close to the visitor.
3751 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
3754 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
3755 if (spdy_version_ > SPDY3) {
3756 // Deflate compression doesn't apply to HPACK.
3757 return;
3759 SpdyFramer framer(spdy_version_);
3760 framer.set_enable_compression(false);
3761 // Construct a SYN_STREAM control frame without compressing the header block,
3762 // and have the framer try to decompress it. This will cause the framer to
3763 // deal with a decompression error.
3764 SpdySynStreamIR syn_stream(1);
3765 syn_stream.set_priority(1);
3766 syn_stream.SetHeader("aa", "alpha beta gamma delta");
3767 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
3768 TestSpdyVisitor visitor(spdy_version_);
3769 visitor.use_compression_ = true;
3770 visitor.SimulateInFramer(
3771 reinterpret_cast<unsigned char*>(control_frame->data()),
3772 control_frame->size());
3773 EXPECT_EQ(1, visitor.error_count_);
3774 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
3775 << SpdyFramer::ErrorCodeToString(framer.error_code());
3776 EXPECT_EQ(0u, visitor.header_buffer_length_);
3779 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3780 SpdyFramer framer(spdy_version_);
3781 // Create a GoAway frame that has a few extra bytes at the end.
3782 // We create enough overhead to overflow the framer's control frame buffer.
3783 ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
3784 const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
3785 const unsigned char kV3FrameData[] = { // Also applies for V2.
3786 0x80, spdy_version_ch_, 0x00, 0x07,
3787 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
3788 0x00, 0x00, 0x00, 0x00, // Stream ID
3789 0x00, 0x00, 0x00, 0x00, // Status
3792 // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
3793 // since it may carry opaque data. Verify that minimal length is tested.
3794 ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
3795 const size_t less_than_min_length =
3796 framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
3797 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3798 const unsigned char kV4FrameData[] = {
3799 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
3800 0x00, 0x00, 0x00, 0x00,
3801 0x00, 0x00, 0x00, 0x00, // Stream Id
3802 0x00, 0x00, 0x00, 0x00, // Status
3803 0x00,
3805 const size_t pad_length =
3806 length + framer.GetControlFrameHeaderSize() -
3807 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
3808 string pad(pad_length, 'A');
3809 TestSpdyVisitor visitor(spdy_version_);
3811 if (IsSpdy4()) {
3812 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3813 } else {
3814 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3816 visitor.SimulateInFramer(
3817 reinterpret_cast<const unsigned char*>(pad.c_str()),
3818 pad.length());
3820 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3821 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3822 visitor.framer_.error_code())
3823 << SpdyFramer::ErrorCodeToString(framer.error_code());
3824 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3827 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3828 SpdyFramer framer(spdy_version_);
3829 SpdySettingsIR settings_ir;
3830 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3831 SetFrameLength(control_frame.get(), 0, spdy_version_);
3832 TestSpdyVisitor visitor(spdy_version_);
3833 visitor.use_compression_ = false;
3834 visitor.SimulateInFramer(
3835 reinterpret_cast<unsigned char*>(control_frame->data()),
3836 framer.GetControlFrameHeaderSize());
3837 if (spdy_version_ <= SPDY3) {
3838 // Should generate an error, since zero-len settings frames are unsupported.
3839 EXPECT_EQ(1, visitor.error_count_);
3840 } else {
3841 // Zero-len settings frames are permitted as of SPDY 4.
3842 EXPECT_EQ(0, visitor.error_count_);
3846 // Tests handling of SETTINGS frames with invalid length.
3847 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3848 SpdyFramer framer(spdy_version_);
3849 SpdySettingsIR settings_ir;
3851 // Add a setting to pad the frame so that we don't get a buffer overflow when
3852 // calling SimulateInFramer() below.
3853 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
3854 false,
3855 false,
3856 0x00000002);
3857 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3858 const size_t kNewLength = 14;
3859 SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
3860 TestSpdyVisitor visitor(spdy_version_);
3861 visitor.use_compression_ = false;
3862 visitor.SimulateInFramer(
3863 reinterpret_cast<unsigned char*>(control_frame->data()),
3864 framer.GetControlFrameHeaderSize() + kNewLength);
3865 // Should generate an error, since its not possible to have a
3866 // settings frame of length kNewLength.
3867 EXPECT_EQ(1, visitor.error_count_);
3870 // Tests handling of SETTINGS frames larger than the frame buffer size.
3871 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3872 SpdyFramer framer(spdy_version_);
3873 SpdySettingsIR settings_ir;
3874 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
3875 false, // persist
3876 false, // persisted
3878 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
3879 false, // persist
3880 false, // persisted
3882 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
3883 false, // persist
3884 false, // persisted
3887 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
3888 EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame->size());
3889 TestSpdyVisitor visitor(spdy_version_);
3890 visitor.use_compression_ = false;
3892 // Read all at once.
3893 visitor.SimulateInFramer(
3894 reinterpret_cast<unsigned char*>(control_frame->data()),
3895 control_frame->size());
3896 EXPECT_EQ(0, visitor.error_count_);
3897 EXPECT_EQ(3, visitor.setting_count_);
3898 if (spdy_version_ > SPDY3) {
3899 EXPECT_EQ(1, visitor.settings_ack_sent_);
3902 // Read data in small chunks.
3903 size_t framed_data = 0;
3904 size_t unframed_data = control_frame->size();
3905 size_t kReadChunkSize = 5; // Read five bytes at a time.
3906 while (unframed_data > 0) {
3907 size_t to_read = std::min(kReadChunkSize, unframed_data);
3908 visitor.SimulateInFramer(
3909 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
3910 to_read);
3911 unframed_data -= to_read;
3912 framed_data += to_read;
3914 EXPECT_EQ(0, visitor.error_count_);
3915 EXPECT_EQ(3 * 2, visitor.setting_count_);
3916 if (spdy_version_ > SPDY3) {
3917 EXPECT_EQ(2, visitor.settings_ack_sent_);
3921 // Tests handling of SETTINGS frame with duplicate entries.
3922 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3923 SpdyFramer framer(spdy_version_);
3925 const unsigned char kV2FrameData[] = {
3926 0x80, spdy_version_ch_, 0x00, 0x04,
3927 0x00, 0x00, 0x00, 0x1C,
3928 0x00, 0x00, 0x00, 0x03,
3929 0x01, 0x00, 0x00, 0x00, // 1st Setting
3930 0x00, 0x00, 0x00, 0x02,
3931 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
3932 0x00, 0x00, 0x00, 0x03,
3933 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
3934 0x00, 0x00, 0x00, 0x03,
3936 const unsigned char kV3FrameData[] = {
3937 0x80, spdy_version_ch_, 0x00, 0x04,
3938 0x00, 0x00, 0x00, 0x1C,
3939 0x00, 0x00, 0x00, 0x03,
3940 0x00, 0x00, 0x00, 0x01, // 1st Setting
3941 0x00, 0x00, 0x00, 0x02,
3942 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
3943 0x00, 0x00, 0x00, 0x03,
3944 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
3945 0x00, 0x00, 0x00, 0x03,
3947 const unsigned char kV4FrameData[] = {
3948 0x00, 0x00, 0x12, 0x04,
3949 0x00, 0x00, 0x00, 0x00,
3950 0x00, 0x00, 0x01, // 1st Setting
3951 0x00, 0x00, 0x00, 0x02,
3952 0x00, 0x01, // 2nd (duplicate) Setting
3953 0x00, 0x00, 0x00, 0x03,
3954 0x00, 0x03, // 3rd (unprocessed) Setting
3955 0x00, 0x00, 0x00, 0x03,
3958 TestSpdyVisitor visitor(spdy_version_);
3959 visitor.use_compression_ = false;
3960 if (IsSpdy2()) {
3961 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
3962 } else if (IsSpdy3()) {
3963 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
3964 } else {
3965 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
3968 if (!IsSpdy4()) {
3969 EXPECT_EQ(1, visitor.setting_count_);
3970 EXPECT_EQ(1, visitor.error_count_);
3971 } else {
3972 // In SPDY 4+, duplicate settings are allowed;
3973 // each setting replaces the previous value for that setting.
3974 EXPECT_EQ(3, visitor.setting_count_);
3975 EXPECT_EQ(0, visitor.error_count_);
3976 EXPECT_EQ(1, visitor.settings_ack_sent_);
3980 // Tests handling of SETTINGS frame with a setting we don't recognize.
3981 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3982 SpdyFramer framer(spdy_version_);
3984 const unsigned char kV2FrameData[] = {
3985 0x80, spdy_version_ch_, 0x00, 0x04,
3986 0x00, 0x00, 0x00, 0x1C,
3987 0x00, 0x00, 0x00, 0x01,
3988 0x10, 0x00, 0x00, 0x00, // 1st Setting
3989 0x00, 0x00, 0x00, 0x02,
3991 const unsigned char kV3FrameData[] = {
3992 0x80, spdy_version_ch_, 0x00, 0x04,
3993 0x00, 0x00, 0x00, 0x1C,
3994 0x00, 0x00, 0x00, 0x01,
3995 0x00, 0x00, 0x00, 0x10, // 1st Setting
3996 0x00, 0x00, 0x00, 0x02,
3998 const unsigned char kV4FrameData[] = {
3999 0x00, 0x00, 0x06, 0x04,
4000 0x00, 0x00, 0x00, 0x00,
4001 0x00, 0x00, 0x10, // 1st Setting
4002 0x00, 0x00, 0x00, 0x02,
4005 TestSpdyVisitor visitor(spdy_version_);
4006 visitor.use_compression_ = false;
4007 if (IsSpdy2()) {
4008 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
4009 } else if (IsSpdy3()) {
4010 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
4011 } else {
4012 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
4015 if (!IsSpdy4()) {
4016 EXPECT_EQ(0, visitor.setting_count_);
4017 EXPECT_EQ(1, visitor.error_count_);
4018 } else {
4019 // In SPDY 4+, we ignore unknown settings because of extensions.
4020 EXPECT_EQ(0, visitor.setting_count_);
4021 EXPECT_EQ(0, visitor.error_count_);
4025 // Tests handling of SETTINGS frame with entries out of order.
4026 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
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 0x02, 0x00, 0x00, 0x00, // 1st Setting
4034 0x00, 0x00, 0x00, 0x02,
4035 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) 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, 0x02, // 1st Setting
4045 0x00, 0x00, 0x00, 0x02,
4046 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
4047 0x00, 0x00, 0x00, 0x03,
4048 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
4049 0x00, 0x00, 0x00, 0x03,
4051 const unsigned char kV4FrameData[] = {
4052 0x00, 0x00, 0x12, 0x04,
4053 0x00, 0x00, 0x00, 0x00,
4054 0x00, 0x00, 0x02, // 1st Setting
4055 0x00, 0x00, 0x00, 0x02,
4056 0x00, 0x01, // 2nd (out of order) 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(kV4FrameData, sizeof(kV4FrameData));
4072 if (!IsSpdy4()) {
4073 EXPECT_EQ(1, visitor.setting_count_);
4074 EXPECT_EQ(1, visitor.error_count_);
4075 } else {
4076 // In SPDY 4+, settings are allowed in any order.
4077 EXPECT_EQ(3, visitor.setting_count_);
4078 EXPECT_EQ(0, visitor.error_count_);
4082 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
4083 if (spdy_version_ <= SPDY3) {
4084 return;
4086 SpdyFramer framer(spdy_version_);
4088 const unsigned char kFrameData[] = {
4089 0x00, 0x00, 0x00, 0x04, 0x01,
4090 0x00, 0x00, 0x00, 0x00,
4093 TestSpdyVisitor visitor(spdy_version_);
4094 visitor.use_compression_ = false;
4095 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4097 EXPECT_EQ(0, visitor.error_count_);
4098 EXPECT_EQ(0, visitor.setting_count_);
4099 EXPECT_EQ(1, visitor.settings_ack_received_);
4102 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
4103 if (spdy_version_ <= SPDY3) {
4104 return;
4107 const int kPaddingLen = 119;
4108 const char data_payload[] = "hello";
4110 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4111 SpdyFramer framer(spdy_version_);
4112 framer.set_visitor(&visitor);
4114 SpdyDataIR data_ir(1, data_payload);
4115 data_ir.set_padding_len(kPaddingLen);
4116 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4117 ASSERT_TRUE(frame.get() != NULL);
4119 int bytes_consumed = 0;
4121 // Send the frame header.
4122 EXPECT_CALL(visitor, OnDataFrameHeader(1,
4123 kPaddingLen + strlen(data_payload),
4124 false));
4125 CHECK_EQ(framer.GetDataFrameMinimumSize(),
4126 framer.ProcessInput(frame->data(),
4127 framer.GetDataFrameMinimumSize()));
4128 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
4129 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4130 bytes_consumed += framer.GetDataFrameMinimumSize();
4132 // Send the padding length field.
4133 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
4134 CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
4135 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4136 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4137 bytes_consumed += 1;
4139 // Send the first two bytes of the data payload, i.e., "he".
4140 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
4141 CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
4142 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
4143 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4144 bytes_consumed += 2;
4146 // Send the rest three bytes of the data payload, i.e., "llo".
4147 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
4148 CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
4149 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4150 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4151 bytes_consumed += 3;
4153 // Send the first 100 bytes of the padding payload.
4154 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
4155 CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
4156 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
4157 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4158 bytes_consumed += 100;
4160 // Send rest of the padding payload.
4161 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
4162 CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
4163 CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
4164 CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
4167 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
4168 SpdyFramer framer(spdy_version_);
4169 scoped_ptr<SpdyFrame> control_frame(
4170 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4171 TestSpdyVisitor visitor(spdy_version_);
4172 visitor.SimulateInFramer(
4173 reinterpret_cast<unsigned char*>(control_frame->data()),
4174 control_frame->size());
4175 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4176 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4179 TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
4180 if (!IsSpdy3()) {
4181 return;
4183 SpdyFramer framer(spdy_version_);
4184 const unsigned char kV3FrameData[] = { // Also applies for V2.
4185 0x80, spdy_version_ch_, 0x00, 0x0A,
4186 0x00, 0x00, 0x00, 0x33,
4187 0x00, 0x03, 0x00, 0x00,
4188 0x00, 0x05, 'p', 'r',
4189 'o', 'o', 'f', 0x00,
4190 0x00, 0x00, 0x06, 'a',
4191 ' ', 'c', 'e', 'r',
4192 't', 0x00, 0x00, 0x00,
4193 0x0C, 'a', 'n', 'o',
4194 't', 'h', 'e', 'r',
4195 ' ', 'c', 'e', 'r',
4196 't', 0x00, 0x00, 0x00,
4197 0x0A, 'f', 'i', 'n',
4198 'a', 'l', ' ', 'c',
4199 'e', 'r', 't',
4201 TestSpdyVisitor visitor(spdy_version_);
4202 visitor.use_compression_ = false;
4203 visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
4204 EXPECT_EQ(0, visitor.error_count_);
4207 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
4208 if (!IsSpdy3()) {
4209 return;
4211 SpdyFramer framer(spdy_version_);
4212 const unsigned char kV3FrameData[] = { // Also applies for V2.
4213 0x80, spdy_version_ch_, 0x00, 0x0A,
4214 0x00, 0x00, 0x00, 0x33,
4215 0x00, 0x03, 0x00, 0x00,
4216 0x00, 0x05, 'p', 'r',
4217 'o', 'o', 'f', 0x00,
4218 0x00, 0x00, 0x06, 'a',
4219 ' ', 'c', 'e', 'r',
4220 't', 0x00, 0x00, 0x00,
4221 0x0C, 'a', 'n', 'o',
4222 't', 'h', 'e', 'r',
4223 ' ', 'c', 'e', 'r',
4224 't', 0x00, 0x00, 0x00,
4225 0x0A, 'f', 'i', 'n',
4226 'a', 'l', ' ', 'c',
4227 'e', 'r', 't',
4229 TestSpdyVisitor visitor(spdy_version_);
4230 visitor.use_compression_ = false;
4231 string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
4232 arraysize(kV3FrameData));
4233 scoped_ptr<SpdyFrame> control_frame(
4234 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
4235 multiple_frame_data.append(string(control_frame->data(),
4236 control_frame->size()));
4237 visitor.SimulateInFramer(
4238 reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
4239 multiple_frame_data.length());
4240 EXPECT_EQ(0, visitor.error_count_);
4241 EXPECT_EQ(1u, visitor.last_window_update_stream_);
4242 EXPECT_EQ(2u, visitor.last_window_update_delta_);
4245 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
4246 if (spdy_version_ <= SPDY3) {
4247 return;
4250 SpdyFramer framer(spdy_version_);
4251 SpdyPushPromiseIR push_promise(42, 57);
4252 push_promise.SetHeader("foo", "bar");
4253 push_promise.SetHeader("bar", "foofoo");
4254 SpdyHeaderBlock headers = push_promise.name_value_block();
4255 scoped_ptr<SpdySerializedFrame> frame(
4256 framer.SerializePushPromise(push_promise));
4257 EXPECT_TRUE(frame.get() != NULL);
4258 TestSpdyVisitor visitor(spdy_version_);
4259 visitor.use_compression_ = true;
4260 visitor.SimulateInFramer(
4261 reinterpret_cast<unsigned char*>(frame->data()),
4262 frame->size());
4263 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
4264 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
4265 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
4268 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
4269 if (spdy_version_ <= SPDY3) {
4270 return;
4273 const unsigned char kInput[] = {
4274 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
4275 0x00, 0x00, 0x00, 0x01, // Stream 1
4276 0x03, // Padding of 3.
4277 0x00, 0x06, 0x63, 0x6f,
4278 0x6f, 0x6b, 0x69, 0x65,
4279 0x07, 0x66, 0x6f, 0x6f,
4280 0x3d, 0x62, 0x61, 0x72,
4281 0x00, 0x00, 0x00,
4283 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4284 0x00, 0x00, 0x00, 0x01, // Stream 1
4285 0x00, 0x06, 0x63, 0x6f,
4286 0x6f, 0x6b, 0x69, 0x65,
4287 0x08, 0x62, 0x61, 0x7a,
4288 0x3d, 0x62, 0x69, 0x6e,
4289 0x67, 0x00, 0x06, 0x63,
4291 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4292 0x00, 0x00, 0x00, 0x01, // Stream 1
4293 0x6f, 0x6f, 0x6b, 0x69,
4294 0x65, 0x00, 0x00, 0x04,
4295 0x6e, 0x61, 0x6d, 0x65,
4296 0x05, 0x76, 0x61, 0x6c,
4297 0x75, 0x65,
4300 TestSpdyVisitor visitor(spdy_version_);
4301 visitor.SimulateInFramer(kInput, sizeof(kInput));
4303 EXPECT_EQ(0, visitor.error_count_);
4304 EXPECT_EQ(1, visitor.headers_frame_count_);
4305 EXPECT_EQ(2, visitor.continuation_count_);
4306 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4307 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4309 EXPECT_THAT(visitor.headers_,
4310 testing::ElementsAre(
4311 testing::Pair("cookie", "foo=bar; baz=bing; "),
4312 testing::Pair("name", "value")));
4315 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
4316 if (spdy_version_ <= SPDY3) {
4317 return;
4320 const unsigned char kInput[] = {
4321 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
4322 0x00, 0x00, 0x00, 0x01, // Stream 1
4323 0x00, 0x06, 0x63, 0x6f,
4324 0x6f, 0x6b, 0x69, 0x65,
4325 0x07, 0x66, 0x6f, 0x6f,
4326 0x3d, 0x62, 0x61, 0x72,
4328 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4329 0x00, 0x00, 0x00, 0x01, // Stream 1
4330 0x00, 0x06, 0x63, 0x6f,
4331 0x6f, 0x6b, 0x69, 0x65,
4332 0x08, 0x62, 0x61, 0x7a,
4333 0x3d, 0x62, 0x69, 0x6e,
4334 0x67, 0x00, 0x06, 0x63,
4336 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
4337 0x00, 0x00, 0x00, 0x01, // Stream 1
4338 0x6f, 0x6f, 0x6b, 0x69,
4339 0x65, 0x00, 0x00, 0x04,
4340 0x6e, 0x61, 0x6d, 0x65,
4341 0x05, 0x76, 0x61, 0x6c,
4342 0x75, 0x65,
4345 SpdyFramer framer(spdy_version_);
4346 TestSpdyVisitor visitor(spdy_version_);
4347 visitor.SimulateInFramer(kInput, sizeof(kInput));
4349 EXPECT_EQ(0, visitor.error_count_);
4350 EXPECT_EQ(1, visitor.headers_frame_count_);
4351 EXPECT_EQ(2, visitor.continuation_count_);
4352 EXPECT_EQ(1, visitor.fin_flag_count_);
4353 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4354 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
4356 EXPECT_THAT(visitor.headers_,
4357 testing::ElementsAre(
4358 testing::Pair("cookie", "foo=bar; baz=bing; "),
4359 testing::Pair("name", "value")));
4362 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
4363 if (spdy_version_ <= SPDY3) {
4364 return;
4367 const unsigned char kInput[] = {
4368 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
4369 0x08, 0x00, 0x00, 0x00, // PADDED
4370 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
4371 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
4372 0x63, 0x6f, 0x6f, 0x6b,
4373 0x69, 0x65, 0x07, 0x66,
4374 0x6f, 0x6f, 0x3d, 0x62,
4375 0x61, 0x72, 0x00, 0x00,
4377 0x00, 0x00, 0x14, 0x09, // CONTINUATION
4378 0x00, 0x00, 0x00, 0x00,
4379 0x01, 0x00, 0x06, 0x63, // Stream 1
4380 0x6f, 0x6f, 0x6b, 0x69,
4381 0x65, 0x08, 0x62, 0x61,
4382 0x7a, 0x3d, 0x62, 0x69,
4383 0x6e, 0x67, 0x00, 0x06,
4384 0x63,
4386 0x00, 0x00, 0x12, 0x09, // CONTINUATION
4387 0x04, 0x00, 0x00, 0x00, // END_HEADERS
4388 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
4389 0x69, 0x65, 0x00, 0x00,
4390 0x04, 0x6e, 0x61, 0x6d,
4391 0x65, 0x05, 0x76, 0x61,
4392 0x6c, 0x75, 0x65,
4395 SpdyFramer framer(spdy_version_);
4396 TestSpdyVisitor visitor(spdy_version_);
4397 visitor.SimulateInFramer(kInput, sizeof(kInput));
4399 EXPECT_EQ(0, visitor.error_count_);
4400 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
4401 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
4402 EXPECT_EQ(2, visitor.continuation_count_);
4403 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4404 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
4406 EXPECT_THAT(visitor.headers_,
4407 testing::ElementsAre(
4408 testing::Pair("cookie", "foo=bar; baz=bing; "),
4409 testing::Pair("name", "value")));
4412 TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
4413 if (spdy_version_ <= SPDY3) {
4414 return;
4417 const unsigned char kInput[] = {
4418 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4419 0x00, 0x00, 0x00, 0x01, // Stream 1
4420 0x00, 0x06, 0x63, 0x6f,
4421 0x6f, 0x6b, 0x69, 0x65,
4422 0x07, 0x66, 0x6f, 0x6f,
4423 0x3d, 0x62, 0x61, 0x72,
4425 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
4426 0x00, 0x00, 0x00, 0x02, // Stream 2
4427 0x00, 0x06, 0x63, 0x6f,
4428 0x6f, 0x6b, 0x69, 0x65,
4429 0x08, 0x62, 0x61, 0x7a,
4430 0x3d, 0x62, 0x69, 0x6e,
4431 0x67, 0x00, 0x06, 0x63,
4434 SpdyFramer framer(spdy_version_);
4435 TestSpdyVisitor visitor(spdy_version_);
4436 framer.set_visitor(&visitor);
4437 visitor.SimulateInFramer(kInput, sizeof(kInput));
4439 EXPECT_EQ(1, visitor.error_count_);
4440 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4441 visitor.framer_.error_code())
4442 << SpdyFramer::ErrorCodeToString(framer.error_code());
4443 EXPECT_EQ(1, visitor.headers_frame_count_);
4444 EXPECT_EQ(0, visitor.continuation_count_);
4445 EXPECT_EQ(0u, visitor.header_buffer_length_);
4448 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
4449 if (spdy_version_ <= SPDY3) {
4450 return;
4453 const unsigned char kInput[] = {
4454 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
4455 0x00, 0x00, 0x00, 0x01, // Stream 1
4456 0x00, 0x06, 0x63, 0x6f,
4457 0x6f, 0x6b, 0x69, 0x65,
4458 0x07, 0x66, 0x6f, 0x6f,
4459 0x3d, 0x62, 0x61, 0x72,
4462 SpdyFramer framer(spdy_version_);
4463 TestSpdyVisitor visitor(spdy_version_);
4464 framer.set_visitor(&visitor);
4465 visitor.SimulateInFramer(kInput, sizeof(kInput));
4467 EXPECT_EQ(1, visitor.error_count_);
4468 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4469 visitor.framer_.error_code())
4470 << SpdyFramer::ErrorCodeToString(framer.error_code());
4471 EXPECT_EQ(0, visitor.continuation_count_);
4472 EXPECT_EQ(0u, visitor.header_buffer_length_);
4475 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
4476 if (spdy_version_ <= SPDY3) {
4477 return;
4480 const unsigned char kInput[] = {
4481 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
4482 0x00, 0x00, 0x00, 0x01, // Stream 1
4483 0x00, 0x06, 0x63, 0x6f,
4484 0x6f, 0x6b, 0x69, 0x65,
4485 0x07, 0x66, 0x6f, 0x6f,
4486 0x3d, 0x62, 0x61, 0x72,
4488 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
4489 0x00, 0x00, 0x00, 0x04,
4490 0xde, 0xad, 0xbe, 0xef,
4493 SpdyFramer framer(spdy_version_);
4494 TestSpdyVisitor visitor(spdy_version_);
4495 framer.set_visitor(&visitor);
4496 visitor.SimulateInFramer(kInput, sizeof(kInput));
4498 EXPECT_EQ(1, visitor.error_count_);
4499 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4500 visitor.framer_.error_code())
4501 << SpdyFramer::ErrorCodeToString(framer.error_code());
4502 EXPECT_EQ(1, visitor.headers_frame_count_);
4503 EXPECT_EQ(0, visitor.continuation_count_);
4504 EXPECT_EQ(0u, visitor.header_buffer_length_);
4505 EXPECT_EQ(0, visitor.data_frame_count_);
4508 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
4509 if (spdy_version_ <= SPDY3) {
4510 return;
4513 const unsigned char kInput[] = {
4514 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
4515 0x00, 0x00, 0x00, 0x01, // Stream 1
4516 0x00, 0x06, 0x63, 0x6f,
4517 0x6f, 0x6b, 0x69, 0x65,
4518 0x07, 0x66, 0x6f, 0x6f,
4519 0x3d, 0x62, 0x61, 0x72,
4521 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
4522 0x00, 0x00, 0x00, 0x01, // Stream 1
4523 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
4524 0x6f, 0x6b, 0x69, 0x65,
4525 0x08, 0x62, 0x61, 0x7a,
4526 0x3d, 0x62, 0x69, 0x6e,
4527 0x67, 0x00, 0x06, 0x63,
4530 SpdyFramer framer(spdy_version_);
4531 TestSpdyVisitor visitor(spdy_version_);
4532 framer.set_visitor(&visitor);
4533 visitor.SimulateInFramer(kInput, sizeof(kInput));
4535 EXPECT_EQ(1, visitor.error_count_);
4536 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
4537 visitor.framer_.error_code())
4538 << SpdyFramer::ErrorCodeToString(framer.error_code());
4539 EXPECT_EQ(1, visitor.headers_frame_count_);
4540 EXPECT_EQ(0, visitor.continuation_count_);
4541 EXPECT_EQ(0u, visitor.header_buffer_length_);
4542 EXPECT_EQ(0, visitor.data_frame_count_);
4545 TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
4546 if (spdy_version_ <= SPDY3) {
4547 return;
4549 const unsigned char kInput[] = {
4550 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
4551 0x00, 0x00, 0x00, 0x01, // Stream 1
4552 0xde, 0xad, 0xbe, 0xef,
4553 0xde, 0xad, 0xbe, 0xef,
4554 0xde, 0xad, 0xbe, 0xef,
4557 TestSpdyVisitor visitor(spdy_version_);
4558 visitor.SimulateInFramer(kInput, sizeof(kInput));
4560 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4561 EXPECT_EQ(0, visitor.error_count_);
4562 EXPECT_EQ(12, visitor.data_bytes_);
4563 EXPECT_EQ(0, visitor.fin_frame_count_);
4564 EXPECT_EQ(0, visitor.fin_flag_count_);
4567 TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
4568 if (spdy_version_ <= SPDY3) {
4569 return;
4571 const unsigned char kInput[] = {
4572 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
4573 0x00, 0x00, 0x00, 0x01, // Stream 1
4574 0x00, 0x06, 0x63, 0x6f,
4575 0x6f, 0x6b, 0x69, 0x65,
4576 0x07, 0x66, 0x6f, 0x6f,
4577 0x3d, 0x62, 0x61, 0x72,
4580 TestSpdyVisitor visitor(spdy_version_);
4581 visitor.SimulateInFramer(kInput, sizeof(kInput));
4583 // TODO(jgraettinger): Verify END_SEGMENT when support is added.
4584 EXPECT_EQ(0, visitor.error_count_);
4585 EXPECT_EQ(1, visitor.headers_frame_count_);
4586 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
4588 EXPECT_THAT(visitor.headers_,
4589 testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
4592 TEST_P(SpdyFramerTest, ReadGarbage) {
4593 SpdyFramer framer(spdy_version_);
4594 unsigned char garbage_frame[256];
4595 memset(garbage_frame, ~0, sizeof(garbage_frame));
4596 TestSpdyVisitor visitor(spdy_version_);
4597 visitor.use_compression_ = false;
4598 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
4599 EXPECT_EQ(1, visitor.error_count_);
4602 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
4603 if (spdy_version_ <= SPDY3) {
4604 return;
4606 SpdyFramer framer(spdy_version_);
4608 // The unrecognized frame type should still have a valid length.
4609 const unsigned char unknown_frame[] = {
4610 0x00, 0x00, 0x08, 0xff, 0xff,
4611 0xff, 0xff, 0xff, 0xff,
4612 0xff, 0xff, 0xff, 0xff,
4613 0xff, 0xff, 0xff, 0xff,
4615 TestSpdyVisitor visitor(spdy_version_);
4617 // Simulate the case where the stream id validation checks out.
4618 visitor.on_unknown_frame_result_ = true;
4619 visitor.use_compression_ = false;
4620 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
4621 EXPECT_EQ(0, visitor.error_count_);
4623 // Follow it up with a valid control frame to make sure we handle
4624 // subsequent frames correctly.
4625 SpdySettingsIR settings_ir;
4626 settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
4627 false, // persist
4628 false, // persisted
4629 10);
4630 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
4631 visitor.SimulateInFramer(
4632 reinterpret_cast<unsigned char*>(control_frame->data()),
4633 control_frame->size());
4634 EXPECT_EQ(0, visitor.error_count_);
4635 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
4636 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
4639 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
4640 if (!IsSpdy4()) {
4641 return;
4643 SpdyFramer framer(spdy_version_);
4644 const unsigned char kFrameData[] = {
4645 0x00, 0x00, 0x08, 0xff, 0xff,
4646 0xff, 0xff, 0xff, 0xff,
4647 0xff, 0xff, 0xff, 0xff,
4648 0xff, 0xff, 0xff, 0xff,
4650 TestSpdyVisitor visitor(spdy_version_);
4651 visitor.use_compression_ = false;
4652 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4653 EXPECT_EQ(1, visitor.error_count_);
4656 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
4657 if (IsSpdy4()) {
4658 // Not valid for SPDY 4 since there is no version field.
4659 return;
4661 SpdyFramer framer(spdy_version_);
4662 const unsigned char kFrameData[] = {
4663 0x80, spdy_version_ch_, 0xff, 0xff,
4664 0xff, 0xff, 0xff, 0xff,
4666 TestSpdyVisitor visitor(spdy_version_);
4667 visitor.use_compression_ = false;
4668 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
4669 EXPECT_EQ(1, visitor.error_count_);
4672 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
4673 if (spdy_version_ <= SPDY3) {
4674 return;
4676 const unsigned char kInput[] = {
4677 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
4678 0x00, 0x00, 0x00, 0x01, // Stream 1
4679 0xef, 0xef, 0xff, 0xff,
4680 0xff, 0xff, 0xff, 0xff,
4681 0xff, 0xff, 0xff, 0xff,
4682 0xff, 0xff, 0xff, 0xff,
4683 0xff, 0xff,
4686 TestSpdyVisitor visitor(spdy_version_);
4687 visitor.SimulateInFramer(kInput, arraysize(kInput));
4688 EXPECT_EQ(1, visitor.error_count_);
4691 TEST_P(SpdyFramerTest, SizesTest) {
4692 SpdyFramer framer(spdy_version_);
4693 if (IsSpdy4()) {
4694 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
4695 EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
4696 EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
4697 EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
4698 EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
4699 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
4700 EXPECT_EQ(17u, framer.GetPingSize());
4701 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
4702 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
4703 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
4704 EXPECT_EQ(9u, framer.GetBlockedSize());
4705 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
4706 EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
4707 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
4708 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
4709 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
4710 } else {
4711 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
4712 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
4713 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
4714 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
4715 EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
4716 EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
4717 EXPECT_EQ(12u, framer.GetPingSize());
4718 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
4719 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
4720 EXPECT_EQ(16u, framer.GetWindowUpdateSize());
4721 EXPECT_EQ(8u, framer.GetFrameMinimumSize());
4722 EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
4723 EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
4727 TEST_P(SpdyFramerTest, StateToStringTest) {
4728 EXPECT_STREQ("ERROR",
4729 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
4730 EXPECT_STREQ("AUTO_RESET",
4731 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
4732 EXPECT_STREQ("RESET",
4733 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
4734 EXPECT_STREQ("READING_COMMON_HEADER",
4735 SpdyFramer::StateToString(
4736 SpdyFramer::SPDY_READING_COMMON_HEADER));
4737 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
4738 SpdyFramer::StateToString(
4739 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
4740 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
4741 SpdyFramer::StateToString(
4742 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
4743 EXPECT_STREQ("FORWARD_STREAM_FRAME",
4744 SpdyFramer::StateToString(
4745 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
4746 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
4747 SpdyFramer::StateToString(
4748 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
4749 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
4750 SpdyFramer::StateToString(
4751 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
4752 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
4753 SpdyFramer::StateToString(
4754 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
4755 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
4756 SpdyFramer::StateToString(
4757 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
4758 EXPECT_STREQ("UNKNOWN_STATE",
4759 SpdyFramer::StateToString(
4760 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
4763 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
4764 EXPECT_STREQ("NO_ERROR",
4765 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
4766 EXPECT_STREQ("INVALID_CONTROL_FRAME",
4767 SpdyFramer::ErrorCodeToString(
4768 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4769 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4770 SpdyFramer::ErrorCodeToString(
4771 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4772 EXPECT_STREQ("ZLIB_INIT_FAILURE",
4773 SpdyFramer::ErrorCodeToString(
4774 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
4775 EXPECT_STREQ("UNSUPPORTED_VERSION",
4776 SpdyFramer::ErrorCodeToString(
4777 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
4778 EXPECT_STREQ("DECOMPRESS_FAILURE",
4779 SpdyFramer::ErrorCodeToString(
4780 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4781 EXPECT_STREQ("COMPRESS_FAILURE",
4782 SpdyFramer::ErrorCodeToString(
4783 SpdyFramer::SPDY_COMPRESS_FAILURE));
4784 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
4785 SpdyFramer::ErrorCodeToString(
4786 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4787 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
4788 SpdyFramer::ErrorCodeToString(
4789 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
4790 EXPECT_STREQ("UNKNOWN_ERROR",
4791 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
4794 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
4795 EXPECT_STREQ("INVALID",
4796 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
4797 EXPECT_STREQ("PROTOCOL_ERROR",
4798 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
4799 EXPECT_STREQ("INVALID_STREAM",
4800 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
4801 EXPECT_STREQ("REFUSED_STREAM",
4802 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
4803 EXPECT_STREQ("UNSUPPORTED_VERSION",
4804 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
4805 EXPECT_STREQ("CANCEL",
4806 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
4807 EXPECT_STREQ("INTERNAL_ERROR",
4808 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
4809 EXPECT_STREQ("FLOW_CONTROL_ERROR",
4810 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
4811 EXPECT_STREQ("UNKNOWN_STATUS",
4812 SpdyFramer::StatusCodeToString(-1));
4815 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
4816 EXPECT_STREQ("DATA",
4817 SpdyFramer::FrameTypeToString(DATA));
4818 EXPECT_STREQ("SYN_STREAM",
4819 SpdyFramer::FrameTypeToString(SYN_STREAM));
4820 EXPECT_STREQ("SYN_REPLY",
4821 SpdyFramer::FrameTypeToString(SYN_REPLY));
4822 EXPECT_STREQ("RST_STREAM",
4823 SpdyFramer::FrameTypeToString(RST_STREAM));
4824 EXPECT_STREQ("SETTINGS",
4825 SpdyFramer::FrameTypeToString(SETTINGS));
4826 EXPECT_STREQ("PING",
4827 SpdyFramer::FrameTypeToString(PING));
4828 EXPECT_STREQ("GOAWAY",
4829 SpdyFramer::FrameTypeToString(GOAWAY));
4830 EXPECT_STREQ("HEADERS",
4831 SpdyFramer::FrameTypeToString(HEADERS));
4832 EXPECT_STREQ("WINDOW_UPDATE",
4833 SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
4834 EXPECT_STREQ("PUSH_PROMISE",
4835 SpdyFramer::FrameTypeToString(PUSH_PROMISE));
4836 EXPECT_STREQ("CREDENTIAL",
4837 SpdyFramer::FrameTypeToString(CREDENTIAL));
4838 EXPECT_STREQ("CONTINUATION",
4839 SpdyFramer::FrameTypeToString(CONTINUATION));
4842 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
4843 if (IsSpdy4()) {
4844 // TODO(hkhalil): catch probable HTTP response in SPDY 4?
4845 return;
4848 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4849 SpdyFramer framer(spdy_version_);
4850 framer.set_visitor(&visitor);
4852 EXPECT_CALL(visitor, OnError(_));
4853 framer.ProcessInput("HTTP/1.1", 8);
4854 EXPECT_TRUE(framer.probable_http_response());
4855 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4856 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4857 << SpdyFramer::ErrorCodeToString(framer.error_code());
4860 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4861 SpdyFramer framer(spdy_version_);
4862 framer.set_visitor(&visitor);
4864 EXPECT_CALL(visitor, OnError(_));
4865 framer.ProcessInput("HTTP/1.0", 8);
4866 EXPECT_TRUE(framer.probable_http_response());
4867 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4868 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4869 << SpdyFramer::ErrorCodeToString(framer.error_code());
4873 TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
4874 if (spdy_version_ > SPDY3) {
4875 return;
4878 uint8 flags = 0;
4879 do {
4880 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4882 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4883 SpdyFramer framer(spdy_version_);
4884 framer.set_visitor(&visitor);
4886 SpdyDataIR data_ir(1, "hello");
4887 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4888 SetFrameFlags(frame.get(), flags, spdy_version_);
4890 if (flags & ~DATA_FLAG_FIN) {
4891 EXPECT_CALL(visitor, OnError(_));
4892 } else {
4893 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4894 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4895 if (flags & DATA_FLAG_FIN) {
4896 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4900 framer.ProcessInput(frame->data(), frame->size());
4901 if (flags & ~DATA_FLAG_FIN) {
4902 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4903 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
4904 framer.error_code())
4905 << SpdyFramer::ErrorCodeToString(framer.error_code());
4906 } else {
4907 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4908 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4909 << SpdyFramer::ErrorCodeToString(framer.error_code());
4911 } while (++flags != 0);
4914 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4915 if (spdy_version_ <= SPDY3) {
4916 return;
4919 uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
4920 DATA_FLAG_PADDED;
4922 uint8 flags = 0;
4923 do {
4924 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4926 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4927 SpdyFramer framer(spdy_version_);
4928 framer.set_visitor(&visitor);
4930 SpdyDataIR data_ir(1, "hello");
4931 scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
4932 SetFrameFlags(frame.get(), flags, spdy_version_);
4934 if (flags & ~valid_data_flags) {
4935 EXPECT_CALL(visitor, OnError(_));
4936 } else {
4937 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4938 if (flags & DATA_FLAG_PADDED) {
4939 // The first byte of payload is parsed as padding length.
4940 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
4941 // Expect Error since the frame ends prematurely.
4942 EXPECT_CALL(visitor, OnError(_));
4943 } else {
4944 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
4945 if (flags & DATA_FLAG_FIN) {
4946 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4951 framer.ProcessInput(frame->data(), frame->size());
4952 if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
4953 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4954 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
4955 << SpdyFramer::ErrorCodeToString(framer.error_code());
4956 } else {
4957 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
4958 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
4959 << SpdyFramer::ErrorCodeToString(framer.error_code());
4961 } while (++flags != 0);
4964 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
4965 if (!IsSpdy2() && !IsSpdy3()) {
4966 // SYN_STREAM not supported in SPDY>3
4967 return;
4969 uint8 flags = 0;
4970 do {
4971 SCOPED_TRACE(testing::Message() << "Flags " << flags);
4973 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4974 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4975 SpdyFramer framer(spdy_version_);
4976 framer.set_visitor(&visitor);
4977 framer.set_debug_visitor(&debug_visitor);
4979 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
4981 SpdySynStreamIR syn_stream(8);
4982 syn_stream.set_associated_to_stream_id(3);
4983 syn_stream.set_priority(1);
4984 syn_stream.SetHeader("foo", "bar");
4985 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
4986 SetFrameFlags(frame.get(), flags, spdy_version_);
4988 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
4989 EXPECT_CALL(visitor, OnError(_));
4990 } else {
4991 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
4992 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
4993 flags & CONTROL_FLAG_UNIDIRECTIONAL));
4994 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
4995 .WillRepeatedly(testing::Return(true));
4996 if (flags & DATA_FLAG_FIN) {
4997 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
4998 } else {
4999 // Do not close the stream if we are expecting a CONTINUATION frame.
5000 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5004 framer.ProcessInput(frame->data(), frame->size());
5005 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
5006 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5007 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5008 framer.error_code())
5009 << SpdyFramer::ErrorCodeToString(framer.error_code());
5010 } else {
5011 EXPECT_EQ(SpdyFramer::SPDY_RESET, 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, SynReplyFrameFlags) {
5019 if (!IsSpdy2() && !IsSpdy3()) {
5020 // SYN_REPLY not supported in SPDY>3
5021 return;
5023 uint8 flags = 0;
5024 do {
5025 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5027 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5028 SpdyFramer framer(spdy_version_);
5029 framer.set_visitor(&visitor);
5031 SpdySynReplyIR syn_reply(37);
5032 syn_reply.SetHeader("foo", "bar");
5033 scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
5034 SetFrameFlags(frame.get(), flags, spdy_version_);
5036 if (flags & ~CONTROL_FLAG_FIN) {
5037 EXPECT_CALL(visitor, OnError(_));
5038 } else {
5039 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
5040 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
5041 .WillRepeatedly(testing::Return(true));
5042 if (flags & DATA_FLAG_FIN) {
5043 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5047 framer.ProcessInput(frame->data(), frame->size());
5048 if (flags & ~CONTROL_FLAG_FIN) {
5049 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5050 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5051 framer.error_code())
5052 << SpdyFramer::ErrorCodeToString(framer.error_code());
5053 } else {
5054 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5055 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5056 << SpdyFramer::ErrorCodeToString(framer.error_code());
5058 } while (++flags != 0);
5061 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
5062 uint8 flags = 0;
5063 do {
5064 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5066 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5067 SpdyFramer framer(spdy_version_);
5068 framer.set_visitor(&visitor);
5070 SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
5071 scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
5072 SetFrameFlags(frame.get(), flags, spdy_version_);
5074 if (flags != 0) {
5075 EXPECT_CALL(visitor, OnError(_));
5076 } else {
5077 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
5080 framer.ProcessInput(frame->data(), frame->size());
5081 if (flags != 0) {
5082 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5083 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5084 framer.error_code())
5085 << SpdyFramer::ErrorCodeToString(framer.error_code());
5086 } else {
5087 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5088 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5089 << SpdyFramer::ErrorCodeToString(framer.error_code());
5091 } while (++flags != 0);
5094 TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
5095 if (spdy_version_ > SPDY3) { return; }
5096 uint8 flags = 0;
5097 do {
5098 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5100 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5101 SpdyFramer framer(spdy_version_);
5102 framer.set_visitor(&visitor);
5104 SpdySettingsIR settings_ir;
5105 settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
5106 false,
5107 false,
5108 54321);
5109 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5110 SetFrameFlags(frame.get(), flags, spdy_version_);
5112 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5113 EXPECT_CALL(visitor, OnError(_));
5114 } else {
5115 EXPECT_CALL(visitor, OnSettings(
5116 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
5117 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
5118 SETTINGS_FLAG_NONE, 54321));
5119 EXPECT_CALL(visitor, OnSettingsEnd());
5122 framer.ProcessInput(frame->data(), frame->size());
5123 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
5124 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5125 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5126 framer.error_code())
5127 << SpdyFramer::ErrorCodeToString(framer.error_code());
5128 } else {
5129 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5130 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5131 << SpdyFramer::ErrorCodeToString(framer.error_code());
5133 } while (++flags != 0);
5136 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
5137 if (spdy_version_ <= SPDY3) { return; }
5138 uint8 flags = 0;
5139 do {
5140 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5142 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5143 SpdyFramer framer(spdy_version_);
5144 framer.set_visitor(&visitor);
5146 SpdySettingsIR settings_ir;
5147 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
5148 scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
5149 SetFrameFlags(frame.get(), flags, spdy_version_);
5151 if (flags != 0) {
5152 EXPECT_CALL(visitor, OnError(_));
5153 } else {
5154 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
5155 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
5156 EXPECT_CALL(visitor, OnSettingsEnd());
5159 framer.ProcessInput(frame->data(), frame->size());
5160 if (flags & ~SETTINGS_FLAG_ACK) {
5161 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5162 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5163 framer.error_code())
5164 << SpdyFramer::ErrorCodeToString(framer.error_code());
5165 } else if (flags & SETTINGS_FLAG_ACK) {
5166 // The frame is invalid because ACK frames should have no payload.
5167 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5168 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5169 framer.error_code())
5170 << SpdyFramer::ErrorCodeToString(framer.error_code());
5171 } else {
5172 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5173 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5174 << SpdyFramer::ErrorCodeToString(framer.error_code());
5176 } while (++flags != 0);
5179 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
5180 uint8 flags = 0;
5181 do {
5182 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5184 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5185 SpdyFramer framer(spdy_version_);
5186 framer.set_visitor(&visitor);
5188 SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
5189 scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
5190 SetFrameFlags(frame.get(), flags, spdy_version_);
5192 if (flags != 0) {
5193 EXPECT_CALL(visitor, OnError(_));
5194 } else {
5195 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
5198 framer.ProcessInput(frame->data(), frame->size());
5199 if (flags != 0) {
5200 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5201 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5202 framer.error_code())
5203 << SpdyFramer::ErrorCodeToString(framer.error_code());
5204 } else {
5205 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5206 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5207 << SpdyFramer::ErrorCodeToString(framer.error_code());
5209 } while (++flags != 0);
5212 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
5213 uint8 flags = 0;
5214 do {
5215 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5217 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5218 SpdyFramer framer(spdy_version_);
5219 framer.set_visitor(&visitor);
5221 SpdyHeadersIR headers_ir(57);
5222 if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
5223 headers_ir.set_priority(3);
5224 headers_ir.set_has_priority(true);
5226 headers_ir.SetHeader("foo", "bar");
5227 scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
5228 uint8 set_flags = flags;
5229 if (IsSpdy4()) {
5230 // TODO(jgraettinger): Add padding to SpdyHeadersIR,
5231 // and implement framing.
5232 set_flags &= ~HEADERS_FLAG_PADDED;
5234 SetFrameFlags(frame.get(), set_flags, spdy_version_);
5236 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5237 EXPECT_CALL(visitor, OnError(_));
5238 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5239 HEADERS_FLAG_END_HEADERS |
5240 HEADERS_FLAG_END_SEGMENT |
5241 HEADERS_FLAG_PADDED |
5242 HEADERS_FLAG_PRIORITY)) {
5243 EXPECT_CALL(visitor, OnError(_));
5244 } else {
5245 if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
5246 EXPECT_CALL(visitor, OnHeaders(57, // stream id
5247 true, // has priority?
5248 3, // priority
5249 flags & CONTROL_FLAG_FIN, // fin?
5250 (flags & HEADERS_FLAG_END_HEADERS) ||
5251 !IsSpdy4())); // end headers?
5252 } else {
5253 EXPECT_CALL(visitor, OnHeaders(57, false, 0,
5254 flags & CONTROL_FLAG_FIN,
5255 (flags & HEADERS_FLAG_END_HEADERS) ||
5256 !IsSpdy4()));
5258 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
5259 .WillRepeatedly(testing::Return(true));
5260 if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
5261 flags & HEADERS_FLAG_END_HEADERS)) {
5262 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
5263 } else {
5264 // Do not close the stream if we are expecting a CONTINUATION frame.
5265 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
5269 framer.ProcessInput(frame->data(), frame->size());
5270 if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
5271 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5272 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5273 framer.error_code())
5274 << SpdyFramer::ErrorCodeToString(framer.error_code());
5275 } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
5276 HEADERS_FLAG_END_HEADERS |
5277 HEADERS_FLAG_END_SEGMENT |
5278 HEADERS_FLAG_PADDED |
5279 HEADERS_FLAG_PRIORITY)) {
5280 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5281 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5282 framer.error_code())
5283 << SpdyFramer::ErrorCodeToString(framer.error_code());
5284 } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
5285 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5286 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5287 << SpdyFramer::ErrorCodeToString(framer.error_code());
5288 } else {
5289 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5290 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5291 << SpdyFramer::ErrorCodeToString(framer.error_code());
5293 } while (++flags != 0);
5296 TEST_P(SpdyFramerTest, PingFrameFlags) {
5297 uint8 flags = 0;
5298 do {
5299 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5301 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5302 SpdyFramer framer(spdy_version_);
5303 framer.set_visitor(&visitor);
5305 scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
5306 SetFrameFlags(frame.get(), flags, spdy_version_);
5308 if (spdy_version_ > SPDY3 &&
5309 flags == PING_FLAG_ACK) {
5310 EXPECT_CALL(visitor, OnPing(42, true));
5311 } else if (flags == 0) {
5312 EXPECT_CALL(visitor, OnPing(42, false));
5313 } else {
5314 EXPECT_CALL(visitor, OnError(_));
5317 framer.ProcessInput(frame->data(), frame->size());
5318 if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
5319 flags == 0) {
5320 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5321 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5322 << SpdyFramer::ErrorCodeToString(framer.error_code());
5323 } else {
5324 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5325 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5326 framer.error_code())
5327 << SpdyFramer::ErrorCodeToString(framer.error_code());
5329 } while (++flags != 0);
5332 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
5333 uint8 flags = 0;
5334 do {
5335 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5337 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5338 SpdyFramer framer(spdy_version_);
5339 framer.set_visitor(&visitor);
5341 scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
5342 SpdyWindowUpdateIR(4, 1024)));
5343 SetFrameFlags(frame.get(), flags, spdy_version_);
5345 if (flags != 0) {
5346 EXPECT_CALL(visitor, OnError(_));
5347 } else {
5348 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
5351 framer.ProcessInput(frame->data(), frame->size());
5352 if (flags != 0) {
5353 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5354 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5355 framer.error_code())
5356 << SpdyFramer::ErrorCodeToString(framer.error_code());
5357 } else {
5358 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5359 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5360 << SpdyFramer::ErrorCodeToString(framer.error_code());
5362 } while (++flags != 0);
5365 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
5366 if (spdy_version_ <= SPDY3) {
5367 return;
5370 uint8 flags = 0;
5371 do {
5372 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5374 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5375 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5376 SpdyFramer framer(spdy_version_);
5377 framer.set_visitor(&visitor);
5378 framer.set_debug_visitor(&debug_visitor);
5380 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
5382 SpdyPushPromiseIR push_promise(42, 57);
5383 push_promise.SetHeader("foo", "bar");
5384 scoped_ptr<SpdySerializedFrame> frame(
5385 framer.SerializePushPromise(push_promise));
5386 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
5387 // and implement framing.
5388 SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
5390 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5391 EXPECT_CALL(visitor, OnError(_));
5392 } else {
5393 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
5394 EXPECT_CALL(visitor, OnPushPromise(42, 57,
5395 flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
5396 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5397 .WillRepeatedly(testing::Return(true));
5400 framer.ProcessInput(frame->data(), frame->size());
5401 if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
5402 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5403 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5404 framer.error_code())
5405 << SpdyFramer::ErrorCodeToString(framer.error_code());
5406 } else {
5407 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5408 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5409 << SpdyFramer::ErrorCodeToString(framer.error_code());
5411 } while (++flags != 0);
5414 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
5415 if (spdy_version_ <= SPDY3) {
5416 return;
5419 uint8 flags = 0;
5420 do {
5421 SCOPED_TRACE(testing::Message() << "Flags " << flags);
5423 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5424 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5425 SpdyFramer framer(spdy_version_);
5426 framer.set_visitor(&visitor);
5427 framer.set_debug_visitor(&debug_visitor);
5429 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
5430 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
5431 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false));
5432 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5433 .WillRepeatedly(testing::Return(true));
5435 SpdyHeadersIR headers_ir(42);
5436 headers_ir.SetHeader("foo", "bar");
5437 scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
5438 SetFrameFlags(frame0.get(), 0, spdy_version_);
5440 SpdyContinuationIR continuation(42);
5441 continuation.SetHeader("foo", "bar");
5442 scoped_ptr<SpdySerializedFrame> frame(
5443 framer.SerializeContinuation(continuation));
5444 SetFrameFlags(frame.get(), flags, spdy_version_);
5446 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5447 EXPECT_CALL(visitor, OnError(_));
5448 } else {
5449 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
5450 EXPECT_CALL(visitor, OnContinuation(42,
5451 flags & HEADERS_FLAG_END_HEADERS));
5452 EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
5453 .WillRepeatedly(testing::Return(true));
5456 framer.ProcessInput(frame0->data(), frame0->size());
5457 framer.ProcessInput(frame->data(), frame->size());
5458 if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
5459 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5460 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
5461 framer.error_code())
5462 << SpdyFramer::ErrorCodeToString(framer.error_code());
5463 } else {
5464 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5465 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5466 << SpdyFramer::ErrorCodeToString(framer.error_code());
5468 } while (++flags != 0);
5471 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
5473 // TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
5475 TEST_P(SpdyFramerTest, EmptySynStream) {
5476 if (!IsSpdy2() && !IsSpdy3()) {
5477 // SYN_STREAM not supported in SPDY>3.
5478 return;
5480 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5481 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
5482 SpdyFramer framer(spdy_version_);
5483 framer.set_visitor(&visitor);
5484 framer.set_debug_visitor(&debug_visitor);
5486 EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
5488 SpdySynStreamIR syn_stream(1);
5489 syn_stream.set_priority(1);
5490 scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
5491 // Adjust size to remove the name/value block.
5492 SetFrameLength(
5493 frame.get(),
5494 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
5495 spdy_version_);
5497 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
5498 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
5499 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
5501 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
5502 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5503 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5504 << SpdyFramer::ErrorCodeToString(framer.error_code());
5507 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
5508 const uint32 kId = 0x020304;
5509 const uint32 kFlags = 0x01;
5510 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
5512 SettingsFlagsAndId id_and_flags =
5513 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
5514 EXPECT_EQ(kId, id_and_flags.id());
5515 EXPECT_EQ(kFlags, id_and_flags.flags());
5516 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
5519 // Test handling of a RST_STREAM with out-of-bounds status codes.
5520 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
5521 const unsigned char kRstStreamStatusTooLow = 0x00;
5522 const unsigned char kRstStreamStatusTooHigh = 0xff;
5523 const unsigned char kV3RstStreamInvalid[] = {
5524 0x80, spdy_version_ch_, 0x00, 0x03,
5525 0x00, 0x00, 0x00, 0x08,
5526 0x00, 0x00, 0x00, 0x01,
5527 0x00, 0x00, 0x00, kRstStreamStatusTooLow
5529 const unsigned char kV4RstStreamInvalid[] = {
5530 0x00, 0x00, 0x04, 0x03,
5531 0x00, 0x00, 0x00, 0x00,
5532 0x01, 0x00, 0x00, 0x00,
5533 kRstStreamStatusTooLow
5536 const unsigned char kV3RstStreamNumStatusCodes[] = {
5537 0x80, spdy_version_ch_, 0x00, 0x03,
5538 0x00, 0x00, 0x00, 0x08,
5539 0x00, 0x00, 0x00, 0x01,
5540 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
5542 const unsigned char kV4RstStreamNumStatusCodes[] = {
5543 0x00, 0x00, 0x04, 0x03,
5544 0x00, 0x00, 0x00, 0x00,
5545 0x01, 0x00, 0x00, 0x00,
5546 kRstStreamStatusTooHigh
5549 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5550 SpdyFramer framer(spdy_version_);
5551 framer.set_visitor(&visitor);
5553 if (IsSpdy4()) {
5554 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5555 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
5556 arraysize(kV4RstStreamInvalid));
5557 } else {
5558 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5559 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
5560 arraysize(kV3RstStreamInvalid));
5562 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5563 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5564 << SpdyFramer::ErrorCodeToString(framer.error_code());
5567 framer.Reset();
5569 if (IsSpdy4()) {
5570 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
5571 framer.ProcessInput(
5572 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
5573 arraysize(kV4RstStreamNumStatusCodes));
5574 } else {
5575 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
5576 framer.ProcessInput(
5577 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
5578 arraysize(kV3RstStreamNumStatusCodes));
5580 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5581 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5582 << SpdyFramer::ErrorCodeToString(framer.error_code());
5585 // Test handling of GOAWAY frames with out-of-bounds status code.
5586 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
5587 if (spdy_version_ <= SPDY2) {
5588 return;
5590 SpdyFramer framer(spdy_version_);
5592 const unsigned char kV3FrameData[] = {
5593 0x80, spdy_version_ch_, 0x00, 0x07,
5594 0x00, 0x00, 0x00, 0x08,
5595 0x00, 0x00, 0x00, 0x01, // Stream Id
5596 0xff, 0xff, 0xff, 0xff, // Status
5598 const unsigned char kV4FrameData[] = {
5599 0x00, 0x00, 0x0a, 0x07,
5600 0x00, 0x00, 0x00, 0x00,
5601 0x00, 0x00, 0x00, 0x00, // Stream id
5602 0x01, 0xff, 0xff, 0xff, // Status
5603 0xff, 0x47, 0x41, // Opaque Description
5605 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5606 framer.set_visitor(&visitor);
5608 if (IsSpdy3()) {
5609 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
5610 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5611 arraysize(kV3FrameData));
5612 } else {
5613 EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
5614 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5615 arraysize(kV4FrameData));
5617 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5618 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5619 << SpdyFramer::ErrorCodeToString(framer.error_code());
5622 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
5623 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
5624 const unsigned char kV2FrameData[] = {
5625 0x80, spdy_version_ch_, 0x00, 0x07,
5626 0x00, 0x00, 0x00, 0x04,
5627 0xff, 0xff, 0xff, 0xff,
5629 const unsigned char kV3FrameData[] = {
5630 0x80, spdy_version_ch_, 0x00, 0x07,
5631 0x00, 0x00, 0x00, 0x08,
5632 0xff, 0xff, 0xff, 0xff,
5633 0x00, 0x00, 0x00, 0x00,
5635 const unsigned char kV4FrameData[] = {
5636 0x00, 0x00, 0x08, 0x07,
5637 0x00, 0x00, 0x00, 0x00,
5638 0x00, 0xff, 0xff, 0xff,
5639 0xff, 0x00, 0x00, 0x00,
5640 0x00,
5643 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5644 SpdyFramer framer(spdy_version_);
5645 framer.set_visitor(&visitor);
5647 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
5648 if (IsSpdy2()) {
5649 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
5650 arraysize(kV2FrameData));
5651 } else if (IsSpdy3()) {
5652 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
5653 arraysize(kV3FrameData));
5654 } else {
5655 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
5656 arraysize(kV4FrameData));
5658 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5659 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5660 << SpdyFramer::ErrorCodeToString(framer.error_code());
5663 TEST_P(SpdyFramerTest, OnBlocked) {
5664 if (spdy_version_ <= SPDY3) {
5665 return;
5668 const SpdyStreamId kStreamId = 0;
5670 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5671 SpdyFramer framer(spdy_version_);
5672 framer.set_visitor(&visitor);
5674 EXPECT_CALL(visitor, OnBlocked(kStreamId));
5676 SpdyBlockedIR blocked_ir(0);
5677 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
5678 framer.ProcessInput(frame->data(), framer.GetBlockedSize());
5680 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5681 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5682 << SpdyFramer::ErrorCodeToString(framer.error_code());
5685 TEST_P(SpdyFramerTest, OnAltSvc) {
5686 if (spdy_version_ <= SPDY3) {
5687 return;
5690 const SpdyStreamId kStreamId = 1;
5692 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5693 SpdyFramer framer(spdy_version_);
5694 framer.set_visitor(&visitor);
5696 SpdyAltSvcWireFormat::AlternativeService altsvc;
5697 altsvc.protocol_id = "p\"=i:d";
5698 altsvc.host = "h_\\o\"st";
5699 altsvc.port = 443;
5700 altsvc.max_age = 10;
5701 altsvc.p = 1.0;
5702 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece("o_r|g!n"), altsvc));
5704 SpdyAltSvcIR altsvc_ir(1);
5705 altsvc_ir.set_max_age(10);
5706 altsvc_ir.set_port(443);
5707 altsvc_ir.set_protocol_id("p\"=i:d");
5708 altsvc_ir.set_host("h_\\o\"st");
5709 altsvc_ir.set_origin("o_r|g!n");
5710 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5711 framer.ProcessInput(frame->data(), frame->size());
5713 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5714 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5715 << SpdyFramer::ErrorCodeToString(framer.error_code());
5718 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
5719 if (spdy_version_ <= SPDY3) {
5720 return;
5723 const SpdyStreamId kStreamId = 1;
5725 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5726 SpdyFramer framer(spdy_version_);
5727 framer.set_visitor(&visitor);
5729 SpdyAltSvcWireFormat::AlternativeService altsvc;
5730 altsvc.protocol_id = "p\"=i:d";
5731 altsvc.host = "h_\\o\"st";
5732 altsvc.port = 443;
5733 altsvc.max_age = 10;
5734 altsvc.p = 1.0;
5735 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece(""), altsvc));
5737 SpdyAltSvcIR altsvc_ir(1);
5738 altsvc_ir.set_max_age(10);
5739 altsvc_ir.set_port(443);
5740 altsvc_ir.set_protocol_id("p\"=i:d");
5741 altsvc_ir.set_host("h_\\o\"st");
5742 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5743 framer.ProcessInput(frame->data(), frame->size());
5745 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5746 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5747 << SpdyFramer::ErrorCodeToString(framer.error_code());
5750 TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
5751 if (spdy_version_ <= SPDY3) {
5752 return;
5755 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5756 SpdyFramer framer(spdy_version_);
5757 framer.set_visitor(&visitor);
5759 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
5761 SpdyAltSvcIR altsvc_ir(1);
5762 altsvc_ir.set_max_age(10);
5763 altsvc_ir.set_port(443);
5764 altsvc_ir.set_host("h1");
5765 altsvc_ir.set_origin("o1");
5766 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5767 framer.ProcessInput(frame->data(), frame->size());
5769 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
5770 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
5771 << SpdyFramer::ErrorCodeToString(framer.error_code());
5774 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
5775 if (spdy_version_ <= SPDY3) {
5776 return;
5779 const SpdyStreamId kStreamId = 1;
5781 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5782 SpdyFramer framer(spdy_version_);
5783 framer.set_visitor(&visitor);
5785 SpdyAltSvcWireFormat::AlternativeService altsvc;
5786 altsvc.protocol_id = "pid";
5787 altsvc.host = "h1";
5788 altsvc.port = 443;
5789 altsvc.max_age = 10;
5790 altsvc.p = 1.0;
5791 EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece(""), altsvc));
5793 SpdyAltSvcIR altsvc_ir(1);
5794 altsvc_ir.set_max_age(10);
5795 altsvc_ir.set_port(443);
5796 altsvc_ir.set_protocol_id("pid");
5797 altsvc_ir.set_host("h1");
5798 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
5799 framer.ProcessInput(frame->data(), frame->size());
5801 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5802 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5803 << SpdyFramer::ErrorCodeToString(framer.error_code());
5806 // Tests handling of ALTSVC frames delivered in small chunks.
5807 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
5808 if (spdy_version_ <= SPDY3) {
5809 return;
5812 SpdyFramer framer(spdy_version_);
5813 SpdyAltSvcIR altsvc_ir(1);
5814 altsvc_ir.set_max_age(20);
5815 altsvc_ir.set_port(443);
5816 altsvc_ir.set_protocol_id("protocolid");
5817 altsvc_ir.set_host("hostname");
5819 scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
5820 TestSpdyVisitor visitor(spdy_version_);
5821 visitor.use_compression_ = false;
5823 // Read data in small chunks.
5824 size_t framed_data = 0;
5825 size_t unframed_data = control_frame->size();
5826 size_t kReadChunkSize = 5; // Read five bytes at a time.
5827 while (unframed_data > 0) {
5828 size_t to_read = std::min(kReadChunkSize, unframed_data);
5829 visitor.SimulateInFramer(
5830 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
5831 to_read);
5832 unframed_data -= to_read;
5833 framed_data += to_read;
5835 EXPECT_EQ(0, visitor.error_count_);
5836 EXPECT_EQ(1, visitor.altsvc_count_);
5837 EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
5838 EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
5839 EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
5840 EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
5843 // Tests handling of PRIORITY frames.
5844 TEST_P(SpdyFramerTest, ReadPriority) {
5845 if (spdy_version_ <= SPDY3) {
5846 return;
5848 SpdyFramer framer(spdy_version_);
5849 SpdyPriorityIR priority(3, 1, 255, false);
5850 scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
5851 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
5852 framer.set_visitor(&visitor);
5853 EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
5854 framer.ProcessInput(frame->data(), frame->size());
5856 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
5857 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
5858 << SpdyFramer::ErrorCodeToString(framer.error_code());
5859 // TODO(mlavan): once we actually maintain a priority tree,
5860 // check that state is adjusted correctly.
5863 TEST_P(SpdyFramerTest, PriorityWeightMapping) {
5864 if (spdy_version_ <= SPDY3) {
5865 return;
5867 SpdyFramer framer(spdy_version_);
5869 EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
5870 EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
5871 EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
5872 EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
5873 EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
5874 EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
5875 EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
5876 EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
5878 EXPECT_EQ(0u, framer.MapWeightToPriority(255));
5879 EXPECT_EQ(0u, framer.MapWeightToPriority(220));
5880 EXPECT_EQ(1u, framer.MapWeightToPriority(219));
5881 EXPECT_EQ(1u, framer.MapWeightToPriority(183));
5882 EXPECT_EQ(2u, framer.MapWeightToPriority(182));
5883 EXPECT_EQ(2u, framer.MapWeightToPriority(147));
5884 EXPECT_EQ(3u, framer.MapWeightToPriority(146));
5885 EXPECT_EQ(3u, framer.MapWeightToPriority(110));
5886 EXPECT_EQ(4u, framer.MapWeightToPriority(109));
5887 EXPECT_EQ(4u, framer.MapWeightToPriority(74));
5888 EXPECT_EQ(5u, framer.MapWeightToPriority(73));
5889 EXPECT_EQ(5u, framer.MapWeightToPriority(37));
5890 EXPECT_EQ(6u, framer.MapWeightToPriority(36));
5891 EXPECT_EQ(6u, framer.MapWeightToPriority(1));
5892 EXPECT_EQ(7u, framer.MapWeightToPriority(0));
5895 // Tests handling of PRIORITY frame with incorrect size.
5896 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
5897 if (spdy_version_ <= SPDY3) {
5898 return;
5901 // PRIORITY frame of size 4, which isn't correct.
5902 const unsigned char kFrameData[] = {
5903 0x00, 0x00, 0x04, 0x02, 0x00,
5904 0x00, 0x00, 0x00, 0x03,
5905 0x00, 0x00, 0x00, 0x01,
5908 TestSpdyVisitor visitor(spdy_version_);
5909 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
5911 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
5912 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
5913 visitor.framer_.error_code())
5914 << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
5917 } // namespace test
5919 } // namespace net