spdy_framer_test.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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. 4 5#include <algorithm> 6#include <iostream> 7#include <limits> 8 9#include "base/compiler_specific.h" 10#include "base/memory/scoped_ptr.h" 11#include "net/spdy/spdy_frame_builder.h" 12#include "net/spdy/spdy_framer.h" 13#include "net/spdy/spdy_protocol.h" 14#include "net/spdy/spdy_test_utils.h" 15#include "testing/gmock/include/gmock/gmock.h" 16#include "testing/platform_test.h" 17 18using std::string; 19using std::max; 20using std::min; 21using std::numeric_limits; 22using testing::_; 23 24namespace net { 25 26namespace test { 27 28static const size_t kMaxDecompressedSize = 1024; 29 30// TODO(akalin): Make sure expectations on mocks are set before mock 31// functions are called, as interleaving expectations and calls is 32// undefined. 33class MockVisitor : public SpdyFramerVisitorInterface { 34 public: 35 MOCK_METHOD1(OnError, void(SpdyFramer* framer)); 36 MOCK_METHOD6(OnSynStream, void(SpdyStreamId stream_id, 37 SpdyStreamId associated_stream_id, 38 SpdyPriority priority, 39 uint8 slot, 40 bool fin, 41 bool unidirectional)); 42 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin)); 43 MOCK_METHOD2(OnHeaders, void(SpdyStreamId stream_id, bool fin)); 44 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id, 45 const char* header_data, 46 size_t len)); 47 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data, 48 size_t len)); 49 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id, 50 size_t length, 51 bool fin)); 52 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id, 53 const char* data, 54 size_t len, 55 bool fin)); 56 MOCK_METHOD1(OnSettings, void(bool clear_persisted)); 57 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value)); 58 MOCK_METHOD1(OnPing, void(uint32 unique_id)); 59 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id, 60 SpdyRstStreamStatus status)); 61 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id, 62 SpdyGoAwayStatus status)); 63 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id, 64 uint32 delta_window_size)); 65 MOCK_METHOD2(OnSynStreamCompressed, 66 void(size_t uncompressed_length, 67 size_t compressed_length)); 68 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id)); 69}; 70 71class SpdyFramerTestUtil { 72 public: 73 // Decompress a single frame using the decompression context held by 74 // the SpdyFramer. The implemention is meant for use only in tests 75 // and will CHECK fail if the input is anything other than a single, 76 // well-formed compressed frame. 77 // 78 // Returns a new decompressed SpdyFrame. 79 template<class SpdyFrameType> static SpdyFrame* DecompressFrame( 80 SpdyFramer* framer, const SpdyFrameType& frame) { 81 DecompressionVisitor visitor(framer->protocol_version()); 82 framer->set_visitor(&visitor); 83 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size())); 84 CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state()); 85 framer->set_visitor(NULL); 86 87 char* buffer = visitor.ReleaseBuffer(); 88 CHECK(buffer != NULL); 89 SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true); 90 if (framer->protocol_version() == 4) { 91 SetFrameLength(decompressed_frame, 92 visitor.size(), 93 framer->protocol_version()); 94 } else { 95 SetFrameLength(decompressed_frame, 96 visitor.size() - framer->GetControlFrameHeaderSize(), 97 framer->protocol_version()); 98 } 99 return decompressed_frame; 100 } 101 102 class DecompressionVisitor : public SpdyFramerVisitorInterface { 103 public: 104 explicit DecompressionVisitor(SpdyMajorVersion version) 105 : version_(version), size_(0), finished_(false) {} 106 107 void ResetBuffer() { 108 CHECK(buffer_.get() == NULL); 109 CHECK_EQ(0u, size_); 110 CHECK(!finished_); 111 buffer_.reset(new char[kMaxDecompressedSize]); 112 } 113 114 virtual void OnSynStream(SpdyStreamId stream_id, 115 SpdyStreamId associated_stream_id, 116 SpdyPriority priority, 117 uint8 slot, 118 bool fin, 119 bool unidirectional) OVERRIDE { 120 SpdyFramer framer(version_); 121 framer.set_enable_compression(false); 122 const SpdyHeaderBlock null_headers; 123 int flags = CONTROL_FLAG_NONE; 124 if (fin) { 125 flags &= CONTROL_FLAG_FIN; 126 } 127 if (unidirectional) { 128 flags &= CONTROL_FLAG_UNIDIRECTIONAL; 129 } 130 scoped_ptr<SpdyFrame> frame( 131 framer.CreateSynStream(stream_id, 132 associated_stream_id, 133 priority, 134 slot, 135 static_cast<SpdyControlFlags>(flags), 136 false, 137 &null_headers)); 138 ResetBuffer(); 139 memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize()); 140 size_ += framer.GetSynStreamMinimumSize(); 141 } 142 143 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE { 144 SpdyFramer framer(version_); 145 framer.set_enable_compression(false); 146 const SpdyHeaderBlock null_headers; 147 int flags = CONTROL_FLAG_NONE; 148 if (fin) { 149 flags &= CONTROL_FLAG_FIN; 150 } 151 scoped_ptr<SpdyFrame> frame( 152 framer.CreateHeaders(stream_id, 153 static_cast<SpdyControlFlags>(flags), 154 false, 155 &null_headers)); 156 ResetBuffer(); 157 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize()); 158 size_ += framer.GetSynStreamMinimumSize(); 159 } 160 161 virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE { 162 SpdyFramer framer(version_); 163 framer.set_enable_compression(false); 164 const SpdyHeaderBlock null_headers; 165 int flags = CONTROL_FLAG_NONE; 166 if (fin) { 167 flags &= CONTROL_FLAG_FIN; 168 } 169 scoped_ptr<SpdyFrame> frame( 170 framer.CreateHeaders(stream_id, 171 static_cast<SpdyControlFlags>(flags), 172 false, 173 &null_headers)); 174 ResetBuffer(); 175 memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize()); 176 size_ += framer.GetSynStreamMinimumSize(); 177 } 178 179 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id, 180 const char* header_data, 181 size_t len) OVERRIDE { 182 CHECK(buffer_.get() != NULL); 183 CHECK_GE(kMaxDecompressedSize, size_ + len); 184 CHECK(!finished_); 185 if (len != 0) { 186 memcpy(buffer_.get() + size_, header_data, len); 187 size_ += len; 188 } else { 189 // Done. 190 finished_ = true; 191 } 192 return true; 193 } 194 195 virtual bool OnCredentialFrameData(const char* /*credential_data*/, 196 size_t /*len*/) OVERRIDE { 197 LOG(FATAL) << "Unexpected CREDENTIAL Frame"; 198 return false; 199 } 200 201 virtual void OnError(SpdyFramer* framer) OVERRIDE { LOG(FATAL); } 202 virtual void OnDataFrameHeader(SpdyStreamId stream_id, 203 size_t length, 204 bool fin) OVERRIDE { 205 LOG(FATAL) << "Unexpected data frame header"; 206 } 207 virtual void OnStreamFrameData(SpdyStreamId stream_id, 208 const char* data, 209 size_t len, 210 bool fin) OVERRIDE { 211 LOG(FATAL); 212 } 213 virtual void OnSetting(SpdySettingsIds id, 214 uint8 flags, 215 uint32 value) OVERRIDE { 216 LOG(FATAL); 217 } 218 virtual void OnSynStreamCompressed( 219 size_t uncompressed_size, 220 size_t compressed_size) OVERRIDE { 221 } 222 virtual void OnPing(uint32 unique_id) OVERRIDE { 223 LOG(FATAL); 224 } 225 virtual void OnRstStream(SpdyStreamId stream_id, 226 SpdyRstStreamStatus status) OVERRIDE { 227 LOG(FATAL); 228 } 229 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, 230 SpdyGoAwayStatus status) OVERRIDE { 231 LOG(FATAL); 232 } 233 virtual void OnWindowUpdate(SpdyStreamId stream_id, 234 uint32 delta_window_size) OVERRIDE { 235 LOG(FATAL); 236 } 237 238 char* ReleaseBuffer() { 239 CHECK(finished_); 240 return buffer_.release(); 241 } 242 243 size_t size() const { 244 CHECK(finished_); 245 return size_; 246 } 247 248 private: 249 SpdyMajorVersion version_; 250 scoped_ptr<char[]> buffer_; 251 size_t size_; 252 bool finished_; 253 254 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor); 255 }; 256 257 private: 258 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil); 259}; 260 261class TestSpdyVisitor : public SpdyFramerVisitorInterface, 262 public SpdyFramerDebugVisitorInterface { 263 public: 264 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024; 265 static const size_t kDefaultCredentialBufferSize = 16 * 1024; 266 267 explicit TestSpdyVisitor(SpdyMajorVersion version) 268 : framer_(version), 269 use_compression_(false), 270 error_count_(0), 271 syn_frame_count_(0), 272 syn_reply_frame_count_(0), 273 headers_frame_count_(0), 274 goaway_count_(0), 275 setting_count_(0), 276 last_window_update_stream_(0), 277 last_window_update_delta_(0), 278 data_bytes_(0), 279 fin_frame_count_(0), 280 fin_flag_count_(0), 281 zero_length_data_frame_count_(0), 282 control_frame_header_data_count_(0), 283 zero_length_control_frame_header_data_count_(0), 284 data_frame_count_(0), 285 last_uncompressed_size_(0), 286 last_compressed_size_(0), 287 header_buffer_(new char[kDefaultHeaderBufferSize]), 288 header_buffer_length_(0), 289 header_buffer_size_(kDefaultHeaderBufferSize), 290 header_stream_id_(-1), 291 header_control_type_(DATA), 292 header_buffer_valid_(false), 293 credential_buffer_(new char[kDefaultCredentialBufferSize]), 294 credential_buffer_length_(0), 295 credential_buffer_size_(kDefaultCredentialBufferSize) { 296 } 297 298 virtual void OnError(SpdyFramer* f) OVERRIDE { 299 LOG(INFO) << "SpdyFramer Error: " 300 << SpdyFramer::ErrorCodeToString(f->error_code()); 301 error_count_++; 302 } 303 304 virtual void OnDataFrameHeader(SpdyStreamId stream_id, 305 size_t length, 306 bool fin) OVERRIDE { 307 data_frame_count_++; 308 header_stream_id_ = stream_id; 309 } 310 311 virtual void OnStreamFrameData(SpdyStreamId stream_id, 312 const char* data, 313 size_t len, 314 bool fin) OVERRIDE { 315 EXPECT_EQ(header_stream_id_, stream_id); 316 if (len == 0) 317 ++zero_length_data_frame_count_; 318 319 data_bytes_ += len; 320 std::cerr << "OnStreamFrameData(" << stream_id << ", \""; 321 if (len > 0) { 322 for (size_t i = 0 ; i < len; ++i) { 323 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec; 324 } 325 } 326 std::cerr << "\", " << len << ")\n"; 327 } 328 329 virtual void OnSynStream(SpdyStreamId stream_id, 330 SpdyStreamId associated_stream_id, 331 SpdyPriority priority, 332 uint8 credential_slot, 333 bool fin, 334 bool unidirectional) OVERRIDE { 335 syn_frame_count_++; 336 InitHeaderStreaming(SYN_STREAM, stream_id); 337 if (fin) { 338 fin_flag_count_++; 339 } 340 } 341 342 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE { 343 syn_reply_frame_count_++; 344 InitHeaderStreaming(HEADERS, stream_id); 345 if (fin) { 346 fin_flag_count_++; 347 } 348 } 349 350 virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE { 351 headers_frame_count_++; 352 InitHeaderStreaming(SYN_REPLY, stream_id); 353 if (fin) { 354 fin_flag_count_++; 355 } 356 } 357 358 virtual void OnSetting(SpdySettingsIds id, 359 uint8 flags, 360 uint32 value) OVERRIDE { 361 setting_count_++; 362 } 363 364 virtual void OnSynStreamCompressed( 365 size_t uncompressed_size, 366 size_t compressed_size) OVERRIDE { 367 } 368 369 virtual void OnPing(uint32 unique_id) OVERRIDE { 370 DLOG(FATAL); 371 } 372 373 virtual void OnRstStream(SpdyStreamId stream_id, 374 SpdyRstStreamStatus status) OVERRIDE { 375 fin_frame_count_++; 376 } 377 378 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, 379 SpdyGoAwayStatus status) OVERRIDE { 380 goaway_count_++; 381 } 382 383 virtual void OnWindowUpdate(SpdyStreamId stream_id, 384 uint32 delta_window_size) OVERRIDE { 385 last_window_update_stream_ = stream_id; 386 last_window_update_delta_ = delta_window_size; 387 } 388 389 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id, 390 const char* header_data, 391 size_t len) OVERRIDE { 392 ++control_frame_header_data_count_; 393 CHECK_EQ(header_stream_id_, stream_id); 394 if (len == 0) { 395 ++zero_length_control_frame_header_data_count_; 396 // Indicates end-of-header-block. 397 CHECK(header_buffer_valid_); 398 size_t parsed_length = framer_.ParseHeaderBlockInBuffer( 399 header_buffer_.get(), header_buffer_length_, &headers_); 400 DCHECK_EQ(header_buffer_length_, parsed_length); 401 return true; 402 } 403 const size_t available = header_buffer_size_ - header_buffer_length_; 404 if (len > available) { 405 header_buffer_valid_ = false; 406 return false; 407 } 408 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len); 409 header_buffer_length_ += len; 410 return true; 411 } 412 413 virtual bool OnCredentialFrameData(const char* credential_data, 414 size_t len) OVERRIDE { 415 if (len == 0) { 416 if (!framer_.ParseCredentialData(credential_buffer_.get(), 417 credential_buffer_length_, 418 &credential_)) { 419 ++error_count_; 420 } 421 return true; 422 } 423 const size_t available = 424 credential_buffer_size_ - credential_buffer_length_; 425 if (len > available) { 426 return false; 427 } 428 memcpy(credential_buffer_.get() + credential_buffer_length_, 429 credential_data, len); 430 credential_buffer_length_ += len; 431 return true; 432 } 433 434 virtual void OnCompressedHeaderBlock(size_t uncompressed_size, 435 size_t compressed_size) OVERRIDE { 436 last_uncompressed_size_ = uncompressed_size; 437 last_compressed_size_ = compressed_size; 438 } 439 440 virtual void OnDecompressedHeaderBlock(size_t decompressed_size, 441 size_t compressed_size) OVERRIDE { 442 last_uncompressed_size_ = decompressed_size; 443 last_compressed_size_ = compressed_size; 444 } 445 446 // Convenience function which runs a framer simulation with particular input. 447 void SimulateInFramer(const unsigned char* input, size_t size) { 448 framer_.set_enable_compression(use_compression_); 449 framer_.set_visitor(this); 450 size_t input_remaining = size; 451 const char* input_ptr = reinterpret_cast<const char*>(input); 452 while (input_remaining > 0 && 453 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) { 454 // To make the tests more interesting, we feed random (amd small) chunks 455 // into the framer. This simulates getting strange-sized reads from 456 // the socket. 457 const size_t kMaxReadSize = 32; 458 size_t bytes_read = 459 (rand() % min(input_remaining, kMaxReadSize)) + 1; 460 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read); 461 input_remaining -= bytes_processed; 462 input_ptr += bytes_processed; 463 } 464 } 465 466 void InitHeaderStreaming(SpdyFrameType header_control_type, 467 SpdyStreamId stream_id) { 468 DCHECK_GE(header_control_type, FIRST_CONTROL_TYPE); 469 DCHECK_LE(header_control_type, LAST_CONTROL_TYPE); 470 memset(header_buffer_.get(), 0, header_buffer_size_); 471 header_buffer_length_ = 0; 472 header_stream_id_ = stream_id; 473 header_control_type_ = header_control_type; 474 header_buffer_valid_ = true; 475 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); 476 } 477 478 // Override the default buffer size (16K). Call before using the framer! 479 void set_header_buffer_size(size_t header_buffer_size) { 480 header_buffer_size_ = header_buffer_size; 481 header_buffer_.reset(new char[header_buffer_size]); 482 } 483 484 static size_t header_data_chunk_max_size() { 485 return SpdyFramer::kHeaderDataChunkMaxSize; 486 } 487 488 SpdyFramer framer_; 489 bool use_compression_; 490 491 // Counters from the visitor callbacks. 492 int error_count_; 493 int syn_frame_count_; 494 int syn_reply_frame_count_; 495 int headers_frame_count_; 496 int goaway_count_; 497 int setting_count_; 498 SpdyStreamId last_window_update_stream_; 499 uint32 last_window_update_delta_; 500 int data_bytes_; 501 int fin_frame_count_; // The count of RST_STREAM type frames received. 502 int fin_flag_count_; // The count of frames with the FIN flag set. 503 int zero_length_data_frame_count_; // The count of zero-length data frames. 504 int control_frame_header_data_count_; // The count of chunks received. 505 // The count of zero-length control frame header data chunks received. 506 int zero_length_control_frame_header_data_count_; 507 int data_frame_count_; 508 size_t last_uncompressed_size_; 509 size_t last_compressed_size_; 510 511 // Header block streaming state: 512 scoped_ptr<char[]> header_buffer_; 513 size_t header_buffer_length_; 514 size_t header_buffer_size_; 515 SpdyStreamId header_stream_id_; 516 SpdyFrameType header_control_type_; 517 bool header_buffer_valid_; 518 SpdyHeaderBlock headers_; 519 520 scoped_ptr<char[]> credential_buffer_; 521 size_t credential_buffer_length_; 522 size_t credential_buffer_size_; 523 SpdyCredential credential_; 524}; 525 526// Retrieves serialized headers from SYN_STREAM frame. 527// Does not check that the given frame is a SYN_STREAM. 528base::StringPiece GetSerializedHeaders(const SpdyFrame* frame, 529 const SpdyFramer& framer) { 530 return base::StringPiece(frame->data() + framer.GetSynStreamMinimumSize(), 531 frame->size() - framer.GetSynStreamMinimumSize()); 532} 533 534} // namespace test 535 536} // namespace net 537 538using net::test::SetFrameLength; 539using net::test::SetFrameFlags; 540using net::test::CompareCharArraysWithHexError; 541using net::test::SpdyFramerTestUtil; 542using net::test::TestSpdyVisitor; 543using net::test::GetSerializedHeaders; 544 545namespace net { 546 547class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> { 548 protected: 549 virtual void SetUp() { 550 spdy_version_ = GetParam(); 551 spdy_version_ch_ = static_cast<unsigned char>(spdy_version_); 552 } 553 554 void CompareFrame(const string& description, 555 const SpdyFrame& actual_frame, 556 const unsigned char* expected, 557 const int expected_len) { 558 const unsigned char* actual = 559 reinterpret_cast<const unsigned char*>(actual_frame.data()); 560 CompareCharArraysWithHexError( 561 description, actual, actual_frame.size(), expected, expected_len); 562 } 563 564 void CompareFrames(const string& description, 565 const SpdyFrame& expected_frame, 566 const SpdyFrame& actual_frame) { 567 CompareCharArraysWithHexError( 568 description, 569 reinterpret_cast<const unsigned char*>(expected_frame.data()), 570 expected_frame.size(), 571 reinterpret_cast<const unsigned char*>(actual_frame.data()), 572 actual_frame.size()); 573 } 574 575 // Returns true if the two header blocks have equivalent content. 576 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected, 577 const SpdyHeaderBlock* actual) { 578 if (expected->size() != actual->size()) { 579 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got " 580 << actual->size() << "."; 581 return false; 582 } 583 for (SpdyHeaderBlock::const_iterator it = expected->begin(); 584 it != expected->end(); 585 ++it) { 586 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first); 587 if (it2 == actual->end()) { 588 LOG(ERROR) << "Expected header name '" << it->first << "'."; 589 return false; 590 } 591 if (it->second.compare(it2->second) != 0) { 592 LOG(ERROR) << "Expected header named '" << it->first 593 << "' to have a value of '" << it->second 594 << "'. The actual value received was '" << it2->second 595 << "'."; 596 return false; 597 } 598 } 599 return true; 600 } 601 602 void AddSpdySettingFromWireFormat(SettingsMap* settings, 603 uint32 key, 604 uint32 value) { 605 SettingsFlagsAndId flags_and_id = 606 SettingsFlagsAndId::FromWireFormat(spdy_version_, key); 607 SpdySettingsIds id = static_cast<SpdySettingsIds>(flags_and_id.id()); 608 SpdySettingsFlags flags = 609 static_cast<SpdySettingsFlags>(flags_and_id.flags()); 610 CHECK(settings->find(id) == settings->end()); 611 settings->insert(std::make_pair(id, SettingsFlagsAndValue(flags, value))); 612 } 613 614 bool IsSpdy2() { return spdy_version_ == SPDY2; } 615 bool IsSpdy3() { return spdy_version_ == SPDY3; } 616 bool IsSpdy4() { return spdy_version_ == SPDY4; } 617 618 // Version of SPDY protocol to be used. 619 SpdyMajorVersion spdy_version_; 620 unsigned char spdy_version_ch_; 621}; 622 623// All tests are run with two different SPDY versions: SPDY/2 and SPDY/3. 624INSTANTIATE_TEST_CASE_P(SpdyFramerTests, 625 SpdyFramerTest, 626 ::testing::Values(SPDY2, SPDY3, SPDY4)); 627 628// Test that we can encode and decode a SpdyHeaderBlock in serialized form. 629TEST_P(SpdyFramerTest, HeaderBlockInBuffer) { 630 SpdyHeaderBlock headers; 631 headers["alpha"] = "beta"; 632 headers["gamma"] = "charlie"; 633 SpdyFramer framer(spdy_version_); 634 framer.set_enable_compression(false); 635 636 // Encode the header block into a SynStream frame. 637 scoped_ptr<SpdyFrame> frame( 638 framer.CreateSynStream(1, // stream id 639 0, // associated stream id 640 1, // priority 641 0, // credential slot 642 CONTROL_FLAG_NONE, 643 false, // compress 644 &headers)); 645 EXPECT_TRUE(frame.get() != NULL); 646 base::StringPiece serialized_headers = 647 GetSerializedHeaders(frame.get(), framer); 648 SpdyHeaderBlock new_headers; 649 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 650 serialized_headers.size(), 651 &new_headers)); 652 653 EXPECT_EQ(headers.size(), new_headers.size()); 654 EXPECT_EQ(headers["alpha"], new_headers["alpha"]); 655 EXPECT_EQ(headers["gamma"], new_headers["gamma"]); 656} 657 658// Test that if there's not a full frame, we fail to parse it. 659TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) { 660 SpdyHeaderBlock headers; 661 headers["alpha"] = "beta"; 662 headers["gamma"] = "charlie"; 663 SpdyFramer framer(spdy_version_); 664 framer.set_enable_compression(false); 665 666 // Encode the header block into a SynStream frame. 667 scoped_ptr<SpdyFrame> frame( 668 framer.CreateSynStream(1, // stream id 669 0, // associated stream id 670 1, // priority 671 0, // credential slot 672 CONTROL_FLAG_NONE, 673 false, // compress 674 &headers)); 675 EXPECT_TRUE(frame.get() != NULL); 676 677 base::StringPiece serialized_headers = 678 GetSerializedHeaders(frame.get(), framer); 679 SpdyHeaderBlock new_headers; 680 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 681 serialized_headers.size() - 2, 682 &new_headers)); 683} 684 685TEST_P(SpdyFramerTest, OutOfOrderHeaders) { 686 SpdyFramer framer(spdy_version_); 687 framer.set_enable_compression(false); 688 689 // Frame builder with plentiful buffer size. 690 SpdyFrameBuilder frame(1024); 691 if (spdy_version_ < 4) { 692 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE); 693 frame.WriteUInt32(3); // stream_id 694 } else { 695 frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3); 696 } 697 698 frame.WriteUInt32(0); // Associated stream id 699 frame.WriteUInt16(0); // Priority. 700 701 if (IsSpdy2()) { 702 frame.WriteUInt16(2); // Number of headers. 703 frame.WriteString("gamma"); 704 frame.WriteString("gamma"); 705 frame.WriteString("alpha"); 706 frame.WriteString("alpha"); 707 } else { 708 frame.WriteUInt32(2); // Number of headers. 709 frame.WriteStringPiece32("gamma"); 710 frame.WriteStringPiece32("gamma"); 711 frame.WriteStringPiece32("alpha"); 712 frame.WriteStringPiece32("alpha"); 713 } 714 // write the length 715 frame.RewriteLength(framer); 716 717 SpdyHeaderBlock new_headers; 718 scoped_ptr<SpdyFrame> control_frame(frame.take()); 719 base::StringPiece serialized_headers = 720 GetSerializedHeaders(control_frame.get(), framer); 721 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 722 serialized_headers.size(), 723 &new_headers)); 724} 725 726TEST_P(SpdyFramerTest, CreateCredential) { 727 SpdyFramer framer(spdy_version_); 728 729 { 730 const char kDescription[] = "CREDENTIAL frame"; 731 const unsigned char kV3FrameData[] = { // Also applies for V2. 732 0x80, spdy_version_ch_, 0x00, 0x0A, 733 0x00, 0x00, 0x00, 0x33, 734 0x00, 0x03, 0x00, 0x00, 735 0x00, 0x05, 'p', 'r', 736 'o', 'o', 'f', 0x00, 737 0x00, 0x00, 0x06, 'a', 738 ' ', 'c', 'e', 'r', 739 't', 0x00, 0x00, 0x00, 740 0x0C, 'a', 'n', 'o', 741 't', 'h', 'e', 'r', 742 ' ', 'c', 'e', 'r', 743 't', 0x00, 0x00, 0x00, 744 0x0A, 'f', 'i', 'n', 745 'a', 'l', ' ', 'c', 746 'e', 'r', 't', 747 }; 748 const unsigned char kV4FrameData[] = { 749 0x00, 0x3b, 0x0A, 0x00, 750 0x00, 0x00, 0x00, 0x00, 751 0x00, 0x03, 0x00, 0x00, 752 0x00, 0x05, 'p', 'r', 753 'o', 'o', 'f', 0x00, 754 0x00, 0x00, 0x06, 'a', 755 ' ', 'c', 'e', 'r', 756 't', 0x00, 0x00, 0x00, 757 0x0C, 'a', 'n', 'o', 758 't', 'h', 'e', 'r', 759 ' ', 'c', 'e', 'r', 760 't', 0x00, 0x00, 0x00, 761 0x0A, 'f', 'i', 'n', 762 'a', 'l', ' ', 'c', 763 'e', 'r', 't', 764 }; 765 SpdyCredential credential; 766 credential.slot = 3; 767 credential.proof = "proof"; 768 credential.certs.push_back("a cert"); 769 credential.certs.push_back("another cert"); 770 credential.certs.push_back("final cert"); 771 scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential)); 772 if (IsSpdy4()) { 773 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 774 } else { 775 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 776 } 777 } 778} 779 780TEST_P(SpdyFramerTest, ParseCredentialFrameData) { 781 SpdyFramer framer(spdy_version_); 782 783 { 784 const unsigned char kV3FrameData[] = { // Also applies for V2. 785 0x80, spdy_version_ch_, 0x00, 0x0A, 786 0x00, 0x00, 0x00, 0x33, 787 0x00, 0x03, 0x00, 0x00, 788 0x00, 0x05, 'p', 'r', 789 'o', 'o', 'f', 0x00, 790 0x00, 0x00, 0x06, 'a', 791 ' ', 'c', 'e', 'r', 792 't', 0x00, 0x00, 0x00, 793 0x0C, 'a', 'n', 'o', 794 't', 'h', 'e', 'r', 795 ' ', 'c', 'e', 'r', 796 't', 0x00, 0x00, 0x00, 797 0x0A, 'f', 'i', 'n', 798 'a', 'l', ' ', 'c', 799 'e', 'r', 't', 800 }; 801 const unsigned char kV4FrameData[] = { 802 0x00, 0x37, 0x0A, 0x00, 803 0x00, 0x00, 0x00, 0x00, 804 0x00, 0x03, 0x00, 0x00, 805 0x00, 0x05, 'p', 'r', 806 'o', 'o', 'f', 0x00, 807 0x00, 0x00, 0x06, 'a', 808 ' ', 'c', 'e', 'r', 809 't', 0x00, 0x00, 0x00, 810 0x0C, 'a', 'n', 'o', 811 't', 'h', 'e', 'r', 812 ' ', 'c', 'e', 'r', 813 't', 0x00, 0x00, 0x00, 814 0x0A, 'f', 'i', 'n', 815 'a', 'l', ' ', 'c', 816 'e', 'r', 't', 817 }; 818 819 SpdyCredential credential; 820 if (IsSpdy4()) { 821 EXPECT_TRUE(SpdyFramer::ParseCredentialData( 822 reinterpret_cast<const char*>(kV4FrameData) + 823 framer.GetControlFrameHeaderSize(), 824 arraysize(kV4FrameData) - framer.GetControlFrameHeaderSize(), 825 &credential)); 826 } else { 827 EXPECT_TRUE(SpdyFramer::ParseCredentialData( 828 reinterpret_cast<const char*>(kV3FrameData) + 829 framer.GetControlFrameHeaderSize(), 830 arraysize(kV3FrameData) - framer.GetControlFrameHeaderSize(), 831 &credential)); 832 } 833 EXPECT_EQ(3u, credential.slot); 834 EXPECT_EQ("proof", credential.proof); 835 EXPECT_EQ("a cert", credential.certs.front()); 836 credential.certs.erase(credential.certs.begin()); 837 EXPECT_EQ("another cert", credential.certs.front()); 838 credential.certs.erase(credential.certs.begin()); 839 EXPECT_EQ("final cert", credential.certs.front()); 840 credential.certs.erase(credential.certs.begin()); 841 EXPECT_TRUE(credential.certs.empty()); 842 } 843} 844 845TEST_P(SpdyFramerTest, DuplicateHeader) { 846 SpdyFramer framer(spdy_version_); 847 // Frame builder with plentiful buffer size. 848 SpdyFrameBuilder frame(1024); 849 if (spdy_version_ < 4) { 850 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE); 851 frame.WriteUInt32(3); // stream_id 852 } else { 853 frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3); 854 } 855 856 frame.WriteUInt32(0); // associated stream id 857 frame.WriteUInt16(0); // Priority. 858 859 if (IsSpdy2()) { 860 frame.WriteUInt16(2); // Number of headers. 861 frame.WriteString("name"); 862 frame.WriteString("value1"); 863 frame.WriteString("name"); 864 frame.WriteString("value2"); 865 } else { 866 frame.WriteUInt32(2); // Number of headers. 867 frame.WriteStringPiece32("name"); 868 frame.WriteStringPiece32("value1"); 869 frame.WriteStringPiece32("name"); 870 frame.WriteStringPiece32("value2"); 871 } 872 // write the length 873 frame.RewriteLength(framer); 874 875 SpdyHeaderBlock new_headers; 876 framer.set_enable_compression(false); 877 scoped_ptr<SpdyFrame> control_frame(frame.take()); 878 base::StringPiece serialized_headers = 879 GetSerializedHeaders(control_frame.get(), framer); 880 // This should fail because duplicate headers are verboten by the spec. 881 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 882 serialized_headers.size(), 883 &new_headers)); 884} 885 886TEST_P(SpdyFramerTest, MultiValueHeader) { 887 SpdyFramer framer(spdy_version_); 888 // Frame builder with plentiful buffer size. 889 SpdyFrameBuilder frame(1024); 890 if (spdy_version_ < 4) { 891 frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE); 892 frame.WriteUInt32(3); // stream_id 893 } else { 894 frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3); 895 } 896 897 frame.WriteUInt32(0); // associated stream id 898 frame.WriteUInt16(0); // Priority. 899 900 string value("value1\0value2"); 901 if (IsSpdy2()) { 902 frame.WriteUInt16(1); // Number of headers. 903 frame.WriteString("name"); 904 frame.WriteString(value); 905 } else { 906 frame.WriteUInt32(1); // Number of headers. 907 frame.WriteStringPiece32("name"); 908 frame.WriteStringPiece32(value); 909 } 910 // write the length 911 frame.RewriteLength(framer); 912 913 SpdyHeaderBlock new_headers; 914 framer.set_enable_compression(false); 915 scoped_ptr<SpdyFrame> control_frame(frame.take()); 916 base::StringPiece serialized_headers = 917 GetSerializedHeaders(control_frame.get(), framer); 918 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 919 serialized_headers.size(), 920 &new_headers)); 921 EXPECT_TRUE(new_headers.find("name") != new_headers.end()); 922 EXPECT_EQ(value, new_headers.find("name")->second); 923} 924 925TEST_P(SpdyFramerTest, BasicCompression) { 926 SpdyHeaderBlock headers; 927 headers["server"] = "SpdyServer 1.0"; 928 headers["date"] = "Mon 12 Jan 2009 12:12:12 PST"; 929 headers["status"] = "200"; 930 headers["version"] = "HTTP/1.1"; 931 headers["content-type"] = "text/html"; 932 headers["content-length"] = "12"; 933 934 scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_)); 935 SpdyFramer framer(spdy_version_); 936 framer.set_debug_visitor(visitor.get()); 937 scoped_ptr<SpdyFrame> frame1( 938 framer.CreateSynStream(1, // stream id 939 0, // associated stream id 940 1, // priority 941 0, // credential slot 942 CONTROL_FLAG_NONE, 943 true, // compress 944 &headers)); 945 if (IsSpdy2()) { 946 EXPECT_EQ(139u, visitor->last_uncompressed_size_); 947#if defined(USE_SYSTEM_ZLIB) 948 EXPECT_EQ(155u, visitor->last_compressed_size_); 949#else // !defined(USE_SYSTEM_ZLIB) 950 EXPECT_EQ(135u, visitor->last_compressed_size_); 951#endif // !defined(USE_SYSTEM_ZLIB) 952 } else { 953 EXPECT_EQ(165u, visitor->last_uncompressed_size_); 954#if defined(USE_SYSTEM_ZLIB) 955 EXPECT_EQ(181u, visitor->last_compressed_size_); 956#else // !defined(USE_SYSTEM_ZLIB) 957 EXPECT_EQ(117u, visitor->last_compressed_size_); 958#endif // !defined(USE_SYSTEM_ZLIB) 959 } 960 scoped_ptr<SpdyFrame> frame2( 961 framer.CreateSynStream(1, // stream id 962 0, // associated stream id 963 1, // priority 964 0, // credential slot 965 CONTROL_FLAG_NONE, 966 true, // compress 967 &headers)); 968 969 // Expect the second frame to be more compact than the first. 970 EXPECT_LE(frame2->size(), frame1->size()); 971 972 // Decompress the first frame 973 scoped_ptr<SpdyFrame> frame3(SpdyFramerTestUtil::DecompressFrame( 974 &framer, *frame1.get())); 975 976 // Decompress the second frame 977 visitor.reset(new TestSpdyVisitor(spdy_version_)); 978 framer.set_debug_visitor(visitor.get()); 979 scoped_ptr<SpdyFrame> frame4(SpdyFramerTestUtil::DecompressFrame( 980 &framer, *frame2.get())); 981 if (IsSpdy2()) { 982 EXPECT_EQ(139u, visitor->last_uncompressed_size_); 983#if defined(USE_SYSTEM_ZLIB) 984 EXPECT_EQ(149u, visitor->last_compressed_size_); 985#else // !defined(USE_SYSTEM_ZLIB) 986 EXPECT_EQ(101u, visitor->last_compressed_size_); 987#endif // !defined(USE_SYSTEM_ZLIB) 988 } else { 989 EXPECT_EQ(165u, visitor->last_uncompressed_size_); 990#if defined(USE_SYSTEM_ZLIB) 991 EXPECT_EQ(175u, visitor->last_compressed_size_); 992#else // !defined(USE_SYSTEM_ZLIB) 993 EXPECT_EQ(102u, visitor->last_compressed_size_); 994#endif // !defined(USE_SYSTEM_ZLIB) 995 } 996 997 // Expect frames 3 & 4 to be the same. 998 CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4); 999 1000 // Expect frames 3 to be the same as a uncompressed frame created 1001 // from scratch. 1002 framer.set_enable_compression(false); 1003 scoped_ptr<SpdyFrame> uncompressed_frame( 1004 framer.CreateSynStream(1, // stream id 1005 0, // associated stream id 1006 1, // priority 1007 0, // credential slot 1008 CONTROL_FLAG_NONE, 1009 false, // compress 1010 &headers)); 1011 CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame); 1012} 1013 1014TEST_P(SpdyFramerTest, CompressEmptyHeaders) { 1015 // See crbug.com/172383 1016 SpdyHeaderBlock headers; 1017 headers["server"] = "SpdyServer 1.0"; 1018 headers["date"] = "Mon 12 Jan 2009 12:12:12 PST"; 1019 headers["status"] = "200"; 1020 headers["version"] = "HTTP/1.1"; 1021 headers["content-type"] = "text/html"; 1022 headers["content-length"] = "12"; 1023 headers["x-empty-header"] = ""; 1024 1025 SpdyFramer framer(spdy_version_); 1026 framer.set_enable_compression(true); 1027 scoped_ptr<SpdyFrame> frame1( 1028 framer.CreateSynStream(1, // stream id 1029 0, // associated stream id 1030 1, // priority 1031 0, // credential slot 1032 CONTROL_FLAG_NONE, 1033 true, // compress 1034 &headers)); 1035} 1036 1037TEST_P(SpdyFramerTest, Basic) { 1038 const unsigned char kV2Input[] = { 1039 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1 1040 0x00, 0x00, 0x00, 0x14, 1041 0x00, 0x00, 0x00, 0x01, 1042 0x00, 0x00, 0x00, 0x00, 1043 0x00, 0x00, 0x00, 0x01, 1044 0x00, 0x02, 'h', 'h', 1045 0x00, 0x02, 'v', 'v', 1046 1047 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1 1048 0x00, 0x00, 0x00, 0x18, 1049 0x00, 0x00, 0x00, 0x01, 1050 0x00, 0x00, 0x00, 0x02, 1051 0x00, 0x02, 'h', '2', 1052 0x00, 0x02, 'v', '2', 1053 0x00, 0x02, 'h', '3', 1054 0x00, 0x02, 'v', '3', 1055 1056 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 1057 0x00, 0x00, 0x00, 0x0c, 1058 0xde, 0xad, 0xbe, 0xef, 1059 0xde, 0xad, 0xbe, 0xef, 1060 0xde, 0xad, 0xbe, 0xef, 1061 1062 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3 1063 0x00, 0x00, 0x00, 0x0c, 1064 0x00, 0x00, 0x00, 0x03, 1065 0x00, 0x00, 0x00, 0x00, 1066 0x00, 0x00, 0x00, 0x00, 1067 1068 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 1069 0x00, 0x00, 0x00, 0x08, 1070 0xde, 0xad, 0xbe, 0xef, 1071 0xde, 0xad, 0xbe, 0xef, 1072 1073 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 1074 0x00, 0x00, 0x00, 0x04, 1075 0xde, 0xad, 0xbe, 0xef, 1076 1077 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1 1078 0x00, 0x00, 0x00, 0x08, 1079 0x00, 0x00, 0x00, 0x01, 1080 0x00, 0x00, 0x00, 0x00, 1081 1082 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 1083 0x00, 0x00, 0x00, 0x00, 1084 1085 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3 1086 0x00, 0x00, 0x00, 0x08, 1087 0x00, 0x00, 0x00, 0x03, 1088 0x00, 0x00, 0x00, 0x00, 1089 }; 1090 1091 const unsigned char kV3Input[] = { 1092 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1 1093 0x00, 0x00, 0x00, 0x1a, 1094 0x00, 0x00, 0x00, 0x01, 1095 0x00, 0x00, 0x00, 0x00, 1096 0x00, 0x00, 0x00, 0x00, 1097 0x00, 0x01, 0x00, 0x00, 1098 0x00, 0x02, 'h', 'h', 1099 0x00, 0x00, 0x00, 0x02, 1100 'v', 'v', 1101 1102 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1 1103 0x00, 0x00, 0x00, 0x20, 1104 0x00, 0x00, 0x00, 0x01, 1105 0x00, 0x00, 0x00, 0x02, 1106 0x00, 0x00, 0x00, 0x02, 1107 'h', '2', 1108 0x00, 0x00, 0x00, 0x02, 1109 'v', '2', 0x00, 0x00, 1110 0x00, 0x02, 'h', '3', 1111 0x00, 0x00, 0x00, 0x02, 1112 'v', '3', 1113 1114 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 1115 0x00, 0x00, 0x00, 0x0c, 1116 0xde, 0xad, 0xbe, 0xef, 1117 0xde, 0xad, 0xbe, 0xef, 1118 0xde, 0xad, 0xbe, 0xef, 1119 1120 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3 1121 0x00, 0x00, 0x00, 0x0e, 1122 0x00, 0x00, 0x00, 0x03, 1123 0x00, 0x00, 0x00, 0x00, 1124 0x00, 0x00, 0x00, 0x00, 1125 0x00, 0x00, 1126 1127 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 1128 0x00, 0x00, 0x00, 0x08, 1129 0xde, 0xad, 0xbe, 0xef, 1130 0xde, 0xad, 0xbe, 0xef, 1131 1132 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 1133 0x00, 0x00, 0x00, 0x04, 1134 0xde, 0xad, 0xbe, 0xef, 1135 1136 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1 1137 0x00, 0x00, 0x00, 0x08, 1138 0x00, 0x00, 0x00, 0x01, 1139 0x00, 0x00, 0x00, 0x00, 1140 1141 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 1142 0x00, 0x00, 0x00, 0x00, 1143 1144 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3 1145 0x00, 0x00, 0x00, 0x08, 1146 0x00, 0x00, 0x00, 0x03, 1147 0x00, 0x00, 0x00, 0x00, 1148 }; 1149 1150 const unsigned char kV4Input[] = { 1151 0x00, 0x1e, 0x01, 0x00, // SYN_STREAM #1 1152 0x00, 0x00, 0x00, 0x01, 1153 0x00, 0x00, 0x00, 0x00, 1154 0x00, 0x00, 0x00, 0x00, 1155 0x00, 0x01, 0x00, 0x00, 1156 0x00, 0x02, 'h', 'h', 1157 0x00, 0x00, 0x00, 0x02, 1158 'v', 'v', 1159 1160 0x00, 0x24, 0x08, 0x00, // HEADERS on Stream #1 1161 0x00, 0x00, 0x00, 0x01, 1162 0x00, 0x00, 0x00, 0x02, 1163 0x00, 0x00, 0x00, 0x02, 1164 'h', '2', 0x00, 0x00, 1165 0x00, 0x02, 'v', '2', 1166 0x00, 0x00, 0x00, 0x02, 1167 'h', '3', 0x00, 0x00, 1168 0x00, 0x02, 'v', '3', 1169 1170 0x00, 0x14, 0x00, 0x00, // DATA on Stream #1 1171 0x00, 0x00, 0x00, 0x01, 1172 0xde, 0xad, 0xbe, 0xef, 1173 0xde, 0xad, 0xbe, 0xef, 1174 0xde, 0xad, 0xbe, 0xef, 1175 1176 0x00, 0x12, 0x01, 0x00, // SYN Stream #3 1177 0x00, 0x00, 0x00, 0x03, 1178 0x00, 0x00, 0x00, 0x00, 1179 0x00, 0x00, 0x00, 0x00, 1180 0x00, 0x00, 1181 1182 0x00, 0x10, 0x00, 0x00, // DATA on Stream #3 1183 0x00, 0x00, 0x00, 0x03, 1184 0xde, 0xad, 0xbe, 0xef, 1185 0xde, 0xad, 0xbe, 0xef, 1186 1187 0x00, 0x0c, 0x00, 0x00, // DATA on Stream #1 1188 0x00, 0x00, 0x00, 0x01, 1189 0xde, 0xad, 0xbe, 0xef, 1190 1191 0x00, 0x0c, 0x03, 0x00, // RST_STREAM on Stream #1 1192 0x00, 0x00, 0x00, 0x01, 1193 0x00, 0x00, 0x00, 0x00, 1194 1195 0x00, 0x08, 0x00, 0x00, // DATA on Stream #3 1196 0x00, 0x00, 0x00, 0x03, 1197 1198 0x00, 0x0c, 0x03, 0x00, // RST_STREAM on Stream #3 1199 0x00, 0x00, 0x00, 0x03, 1200 0x00, 0x00, 0x00, 0x00, 1201 }; 1202 1203 TestSpdyVisitor visitor(spdy_version_); 1204 if (IsSpdy2()) { 1205 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input)); 1206 } else if (IsSpdy3()) { 1207 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input)); 1208 } else { 1209 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input)); 1210 } 1211 1212 EXPECT_EQ(0, visitor.error_count_); 1213 EXPECT_EQ(2, visitor.syn_frame_count_); 1214 EXPECT_EQ(0, visitor.syn_reply_frame_count_); 1215 EXPECT_EQ(1, visitor.headers_frame_count_); 1216 EXPECT_EQ(24, visitor.data_bytes_); 1217 EXPECT_EQ(2, visitor.fin_frame_count_); 1218 EXPECT_EQ(0, visitor.fin_flag_count_); 1219 EXPECT_EQ(0, visitor.zero_length_data_frame_count_); 1220 EXPECT_EQ(4, visitor.data_frame_count_); 1221} 1222 1223// Test that the FIN flag on a data frame signifies EOF. 1224TEST_P(SpdyFramerTest, FinOnDataFrame) { 1225 const unsigned char kV2Input[] = { 1226 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1 1227 0x00, 0x00, 0x00, 0x14, 1228 0x00, 0x00, 0x00, 0x01, 1229 0x00, 0x00, 0x00, 0x00, 1230 0x00, 0x00, 0x00, 0x01, 1231 0x00, 0x02, 'h', 'h', 1232 0x00, 0x02, 'v', 'v', 1233 1234 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1 1235 0x00, 0x00, 0x00, 0x10, 1236 0x00, 0x00, 0x00, 0x01, 1237 0x00, 0x00, 0x00, 0x01, 1238 0x00, 0x02, 'a', 'a', 1239 0x00, 0x02, 'b', 'b', 1240 1241 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 1242 0x00, 0x00, 0x00, 0x0c, 1243 0xde, 0xad, 0xbe, 0xef, 1244 0xde, 0xad, 0xbe, 0xef, 1245 0xde, 0xad, 0xbe, 0xef, 1246 1247 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF 1248 0x01, 0x00, 0x00, 0x04, 1249 0xde, 0xad, 0xbe, 0xef, 1250 }; 1251 const unsigned char kV3Input[] = { 1252 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1 1253 0x00, 0x00, 0x00, 0x1a, 1254 0x00, 0x00, 0x00, 0x01, 1255 0x00, 0x00, 0x00, 0x00, 1256 0x00, 0x00, 0x00, 0x00, 1257 0x00, 0x01, 0x00, 0x00, 1258 0x00, 0x02, 'h', 'h', 1259 0x00, 0x00, 0x00, 0x02, 1260 'v', 'v', 1261 1262 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1 1263 0x00, 0x00, 0x00, 0x14, 1264 0x00, 0x00, 0x00, 0x01, 1265 0x00, 0x00, 0x00, 0x01, 1266 0x00, 0x00, 0x00, 0x02, 1267 'a', 'a', 0x00, 0x00, 1268 0x00, 0x02, 'b', 'b', 1269 1270 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 1271 0x00, 0x00, 0x00, 0x0c, 1272 0xde, 0xad, 0xbe, 0xef, 1273 0xde, 0xad, 0xbe, 0xef, 1274 0xde, 0xad, 0xbe, 0xef, 1275 1276 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF 1277 0x01, 0x00, 0x00, 0x04, 1278 0xde, 0xad, 0xbe, 0xef, 1279 }; 1280 const unsigned char kV4Input[] = { 1281 0x00, 0x1e, 0x01, 0x00, // SYN_STREAM #1 1282 0x00, 0x00, 0x00, 0x01, 1283 0x00, 0x00, 0x00, 0x00, 1284 0x00, 0x00, 0x00, 0x00, 1285 0x00, 0x01, 0x00, 0x00, 1286 0x00, 0x02, 'h', 'h', 1287 0x00, 0x00, 0x00, 0x02, 1288 'v', 'v', 1289 1290 0x00, 0x18, 0x02, 0x00, // SYN REPLY Stream #1 1291 0x00, 0x00, 0x00, 0x01, 1292 0x00, 0x00, 0x00, 0x01, 1293 0x00, 0x00, 0x00, 0x02, 1294 'a', 'a', 0x00, 0x00, 1295 0x00, 0x02, 'b', 'b', 1296 1297 0x00, 0x14, 0x00, 0x00, // DATA on Stream #1 1298 0x00, 0x00, 0x00, 0x01, 1299 0xde, 0xad, 0xbe, 0xef, 1300 0xde, 0xad, 0xbe, 0xef, 1301 0xde, 0xad, 0xbe, 0xef, 1302 1303 0x00, 0x0c, 0x00, 0x01, // DATA on Stream #1, with FIN 1304 0x00, 0x00, 0x00, 0x01, 1305 0xde, 0xad, 0xbe, 0xef, 1306 }; 1307 1308 TestSpdyVisitor visitor(spdy_version_); 1309 if (IsSpdy2()) { 1310 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input)); 1311 } else if (IsSpdy3()) { 1312 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input)); 1313 } else { 1314 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input)); 1315 } 1316 1317 EXPECT_EQ(0, visitor.error_count_); 1318 EXPECT_EQ(1, visitor.syn_frame_count_); 1319 EXPECT_EQ(1, visitor.syn_reply_frame_count_); 1320 EXPECT_EQ(0, visitor.headers_frame_count_); 1321 EXPECT_EQ(16, visitor.data_bytes_); 1322 EXPECT_EQ(0, visitor.fin_frame_count_); 1323 EXPECT_EQ(0, visitor.fin_flag_count_); 1324 EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 1325 EXPECT_EQ(2, visitor.data_frame_count_); 1326} 1327 1328// Test that the FIN flag on a SYN reply frame signifies EOF. 1329TEST_P(SpdyFramerTest, FinOnSynReplyFrame) { 1330 const unsigned char kV2Input[] = { 1331 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1 1332 0x00, 0x00, 0x00, 0x14, 1333 0x00, 0x00, 0x00, 0x01, 1334 0x00, 0x00, 0x00, 0x00, 1335 0x00, 0x00, 0x00, 0x01, 1336 0x00, 0x02, 'h', 'h', 1337 0x00, 0x02, 'v', 'v', 1338 1339 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1 1340 0x01, 0x00, 0x00, 0x10, 1341 0x00, 0x00, 0x00, 0x01, 1342 0x00, 0x00, 0x00, 0x01, 1343 0x00, 0x02, 'a', 'a', 1344 0x00, 0x02, 'b', 'b', 1345 }; 1346 const unsigned char kV3Input[] = { 1347 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1 1348 0x00, 0x00, 0x00, 0x1a, 1349 0x00, 0x00, 0x00, 0x01, 1350 0x00, 0x00, 0x00, 0x00, 1351 0x00, 0x00, 0x00, 0x00, 1352 0x00, 0x01, 0x00, 0x00, 1353 0x00, 0x02, 'h', 'h', 1354 0x00, 0x00, 0x00, 0x02, 1355 'v', 'v', 1356 1357 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1 1358 0x01, 0x00, 0x00, 0x14, 1359 0x00, 0x00, 0x00, 0x01, 1360 0x00, 0x00, 0x00, 0x01, 1361 0x00, 0x00, 0x00, 0x02, 1362 'a', 'a', 0x00, 0x00, 1363 0x00, 0x02, 'b', 'b', 1364 }; 1365 const unsigned char kV4Input[] = { 1366 0x00, 0x1e, 0x01, 0x00, // SYN_STREAM #1 1367 0x00, 0x00, 0x00, 0x01, 1368 0x00, 0x00, 0x00, 0x00, 1369 0x00, 0x00, 0x00, 0x00, 1370 0x00, 0x01, 0x00, 0x00, 1371 0x00, 0x02, 'h', 'h', 1372 0x00, 0x00, 0x00, 0x02, 1373 'v', 'v', 1374 1375 0x00, 0x18, 0x02, 0x01, // SYN_REPLY #1, with FIN 1376 0x00, 0x00, 0x00, 0x01, 1377 0x00, 0x00, 0x00, 0x01, 1378 0x00, 0x00, 0x00, 0x02, 1379 'a', 'a', 0x00, 0x00, 1380 0x00, 0x02, 'b', 'b', 1381 }; 1382 1383 TestSpdyVisitor visitor(spdy_version_); 1384 if (IsSpdy2()) { 1385 visitor.SimulateInFramer(kV2Input, sizeof(kV2Input)); 1386 } else if (IsSpdy3()) { 1387 visitor.SimulateInFramer(kV3Input, sizeof(kV3Input)); 1388 } else { 1389 visitor.SimulateInFramer(kV4Input, sizeof(kV4Input)); 1390 } 1391 1392 EXPECT_EQ(0, visitor.error_count_); 1393 EXPECT_EQ(1, visitor.syn_frame_count_); 1394 EXPECT_EQ(1, visitor.syn_reply_frame_count_); 1395 EXPECT_EQ(0, visitor.headers_frame_count_); 1396 EXPECT_EQ(0, visitor.data_bytes_); 1397 EXPECT_EQ(0, visitor.fin_frame_count_); 1398 EXPECT_EQ(1, visitor.fin_flag_count_); 1399 EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 1400 EXPECT_EQ(0, visitor.data_frame_count_); 1401} 1402 1403TEST_P(SpdyFramerTest, HeaderCompression) { 1404 SpdyFramer send_framer(spdy_version_); 1405 SpdyFramer recv_framer(spdy_version_); 1406 1407 send_framer.set_enable_compression(true); 1408 recv_framer.set_enable_compression(true); 1409 1410 const char kHeader1[] = "header1"; 1411 const char kHeader2[] = "header2"; 1412 const char kHeader3[] = "header3"; 1413 const char kValue1[] = "value1"; 1414 const char kValue2[] = "value2"; 1415 const char kValue3[] = "value3"; 1416 1417 // SYN_STREAM #1 1418 SpdyHeaderBlock block; 1419 block[kHeader1] = kValue1; 1420 block[kHeader2] = kValue2; 1421 SpdyControlFlags flags(CONTROL_FLAG_NONE); 1422 SpdySynStreamIR syn_ir_1(1); 1423 syn_ir_1.SetHeader(kHeader1, kValue1); 1424 syn_ir_1.SetHeader(kHeader2, kValue2); 1425 scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeSynStream(syn_ir_1)); 1426 EXPECT_TRUE(syn_frame_1.get() != NULL); 1427 1428 // SYN_STREAM #2 1429 block[kHeader3] = kValue3; 1430 scoped_ptr<SpdyFrame> syn_frame_2( 1431 send_framer.CreateSynStream(3, // stream id 1432 0, // associated stream id 1433 0, // priority 1434 0, // credential slot 1435 flags, 1436 true, // compress 1437 &block)); 1438 EXPECT_TRUE(syn_frame_2.get() != NULL); 1439 1440 // Now start decompressing 1441 scoped_ptr<SpdyFrame> decompressed; 1442 scoped_ptr<SpdyFrame> uncompressed; 1443 base::StringPiece serialized_headers; 1444 SpdyHeaderBlock decompressed_headers; 1445 1446 // Decompress SYN_STREAM #1 1447 decompressed.reset(SpdyFramerTestUtil::DecompressFrame( 1448 &recv_framer, *syn_frame_1.get())); 1449 EXPECT_TRUE(decompressed.get() != NULL); 1450 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer); 1451 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 1452 serialized_headers.size(), 1453 &decompressed_headers)); 1454 EXPECT_EQ(2u, decompressed_headers.size()); 1455 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]); 1456 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]); 1457 1458 // Decompress SYN_STREAM #2 1459 decompressed.reset(SpdyFramerTestUtil::DecompressFrame( 1460 &recv_framer, *syn_frame_2.get())); 1461 EXPECT_TRUE(decompressed.get() != NULL); 1462 serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer); 1463 decompressed_headers.clear(); 1464 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(), 1465 serialized_headers.size(), 1466 &decompressed_headers)); 1467 EXPECT_EQ(3u, decompressed_headers.size()); 1468 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]); 1469 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]); 1470 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]); 1471} 1472 1473// Verify we don't leak when we leave streams unclosed 1474TEST_P(SpdyFramerTest, UnclosedStreamDataCompressors) { 1475 SpdyFramer send_framer(spdy_version_); 1476 1477 send_framer.set_enable_compression(true); 1478 1479 const char kHeader1[] = "header1"; 1480 const char kHeader2[] = "header2"; 1481 const char kValue1[] = "value1"; 1482 const char kValue2[] = "value2"; 1483 1484 SpdyHeaderBlock block; 1485 block[kHeader1] = kValue1; 1486 block[kHeader2] = kValue2; 1487 SpdyControlFlags flags(CONTROL_FLAG_NONE); 1488 scoped_ptr<SpdyFrame> syn_frame( 1489 send_framer.CreateSynStream(1, // stream id 1490 0, // associated stream id 1491 0, // priority 1492 0, // credential slot 1493 flags, 1494 true, // compress 1495 &block)); 1496 EXPECT_TRUE(syn_frame.get() != NULL); 1497 1498 const char bytes[] = "this is a test test test test test!"; 1499 scoped_ptr<SpdyFrame> send_frame( 1500 send_framer.CreateDataFrame( 1501 1, bytes, arraysize(bytes), 1502 static_cast<SpdyDataFlags>(DATA_FLAG_FIN))); 1503 EXPECT_TRUE(send_frame.get() != NULL); 1504 1505 // Run the inputs through the framer. 1506 TestSpdyVisitor visitor(spdy_version_); 1507 visitor.use_compression_ = true; 1508 const unsigned char* data; 1509 data = reinterpret_cast<const unsigned char*>(syn_frame->data()); 1510 visitor.SimulateInFramer(data, syn_frame->size()); 1511 data = reinterpret_cast<const unsigned char*>(send_frame->data()); 1512 visitor.SimulateInFramer(data, send_frame->size()); 1513 1514 EXPECT_EQ(0, visitor.error_count_); 1515 EXPECT_EQ(1, visitor.syn_frame_count_); 1516 EXPECT_EQ(0, visitor.syn_reply_frame_count_); 1517 EXPECT_EQ(0, visitor.headers_frame_count_); 1518 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_)); 1519 EXPECT_EQ(0, visitor.fin_frame_count_); 1520 EXPECT_EQ(0, visitor.fin_flag_count_); 1521 EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 1522 EXPECT_EQ(1, visitor.data_frame_count_); 1523} 1524 1525// Verify we can decompress the stream even if handed over to the 1526// framer 1 byte at a time. 1527TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) { 1528 SpdyFramer send_framer(spdy_version_); 1529 1530 send_framer.set_enable_compression(true); 1531 1532 const char kHeader1[] = "header1"; 1533 const char kHeader2[] = "header2"; 1534 const char kValue1[] = "value1"; 1535 const char kValue2[] = "value2"; 1536 1537 SpdyHeaderBlock block; 1538 block[kHeader1] = kValue1; 1539 block[kHeader2] = kValue2; 1540 SpdyControlFlags flags(CONTROL_FLAG_NONE); 1541 scoped_ptr<SpdyFrame> syn_frame( 1542 send_framer.CreateSynStream(1, // stream id 1543 0, // associated stream id 1544 0, // priority 1545 0, // credential slot 1546 flags, 1547 true, // compress 1548 &block)); 1549 EXPECT_TRUE(syn_frame.get() != NULL); 1550 1551 const char bytes[] = "this is a test test test test test!"; 1552 scoped_ptr<SpdyFrame> send_frame( 1553 send_framer.CreateDataFrame( 1554 1, bytes, arraysize(bytes), 1555 static_cast<SpdyDataFlags>(DATA_FLAG_FIN))); 1556 EXPECT_TRUE(send_frame.get() != NULL); 1557 1558 // Run the inputs through the framer. 1559 TestSpdyVisitor visitor(spdy_version_); 1560 visitor.use_compression_ = true; 1561 const unsigned char* data; 1562 data = reinterpret_cast<const unsigned char*>(syn_frame->data()); 1563 for (size_t idx = 0; idx < syn_frame->size(); ++idx) { 1564 visitor.SimulateInFramer(data + idx, 1); 1565 ASSERT_EQ(0, visitor.error_count_); 1566 } 1567 data = reinterpret_cast<const unsigned char*>(send_frame->data()); 1568 for (size_t idx = 0; idx < send_frame->size(); ++idx) { 1569 visitor.SimulateInFramer(data + idx, 1); 1570 ASSERT_EQ(0, visitor.error_count_); 1571 } 1572 1573 EXPECT_EQ(0, visitor.error_count_); 1574 EXPECT_EQ(1, visitor.syn_frame_count_); 1575 EXPECT_EQ(0, visitor.syn_reply_frame_count_); 1576 EXPECT_EQ(0, visitor.headers_frame_count_); 1577 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_)); 1578 EXPECT_EQ(0, visitor.fin_frame_count_); 1579 EXPECT_EQ(0, visitor.fin_flag_count_); 1580 EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 1581 EXPECT_EQ(1, visitor.data_frame_count_); 1582} 1583 1584TEST_P(SpdyFramerTest, WindowUpdateFrame) { 1585 SpdyFramer framer(spdy_version_); 1586 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x12345678)); 1587 1588 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678"; 1589 const unsigned char kV3FrameData[] = { // Also applies for V2. 1590 0x80, spdy_version_ch_, 0x00, 0x09, 1591 0x00, 0x00, 0x00, 0x08, 1592 0x00, 0x00, 0x00, 0x01, 1593 0x12, 0x34, 0x56, 0x78 1594 }; 1595 const unsigned char kV4FrameData[] = { 1596 0x00, 0x0c, 0x09, 0x00, 1597 0x00, 0x00, 0x00, 0x01, 1598 0x12, 0x34, 0x56, 0x78 1599 }; 1600 1601 if (IsSpdy4()) { 1602 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1603 } else { 1604 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1605 } 1606} 1607 1608TEST_P(SpdyFramerTest, CreateDataFrame) { 1609 SpdyFramer framer(spdy_version_); 1610 1611 { 1612 const char kDescription[] = "'hello' data frame, no FIN"; 1613 const unsigned char kV3FrameData[] = { // Also applies for V2. 1614 0x00, 0x00, 0x00, 0x01, 1615 0x00, 0x00, 0x00, 0x05, 1616 'h', 'e', 'l', 'l', 1617 'o' 1618 }; 1619 const unsigned char kV4FrameData[] = { 1620 0x00, 0x0d, 0x00, 0x00, 1621 0x00, 0x00, 0x00, 0x01, 1622 'h', 'e', 'l', 'l', 1623 'o' 1624 }; 1625 const char bytes[] = "hello"; 1626 1627 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 1628 1, bytes, strlen(bytes), DATA_FLAG_NONE)); 1629 if (IsSpdy4()) { 1630 CompareFrame( 1631 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1632 } else { 1633 CompareFrame( 1634 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1635 } 1636 1637 SpdyDataIR data_ir(1); 1638 data_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes))); 1639 frame.reset(framer.SerializeDataFrameHeader(data_ir)); 1640 CompareCharArraysWithHexError( 1641 kDescription, 1642 reinterpret_cast<const unsigned char*>(frame->data()), 1643 framer.GetDataFrameMinimumSize(), 1644 IsSpdy4() ? kV4FrameData : kV3FrameData, 1645 framer.GetDataFrameMinimumSize()); 1646 } 1647 1648 { 1649 const char kDescription[] = "Data frame with negative data byte, no FIN"; 1650 const unsigned char kV3FrameData[] = { // Also applies for V2. 1651 0x00, 0x00, 0x00, 0x01, 1652 0x00, 0x00, 0x00, 0x01, 1653 0xff 1654 }; 1655 const unsigned char kV4FrameData[] = { 1656 0x00, 0x09, 0x00, 0x00, 1657 0x00, 0x00, 0x00, 0x01, 1658 0xff 1659 }; 1660 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 1661 1, "\xff", 1, DATA_FLAG_NONE)); 1662 if (IsSpdy4()) { 1663 CompareFrame( 1664 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1665 } else { 1666 CompareFrame( 1667 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1668 } 1669 } 1670 1671 { 1672 const char kDescription[] = "'hello' data frame, with FIN"; 1673 const unsigned char kV3FrameData[] = { // Also applies for V2. 1674 0x00, 0x00, 0x00, 0x01, 1675 0x01, 0x00, 0x00, 0x05, 1676 'h', 'e', 'l', 'l', 1677 'o' 1678 }; 1679 const unsigned char kV4FrameData[] = { 1680 0x00, 0x0d, 0x00, 0x01, 1681 0x00, 0x00, 0x00, 0x01, 1682 'h', 'e', 'l', 'l', 1683 'o' 1684 }; 1685 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 1686 1, "hello", 5, DATA_FLAG_FIN)); 1687 if (IsSpdy4()) { 1688 CompareFrame( 1689 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1690 } else { 1691 CompareFrame( 1692 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1693 } 1694 } 1695 1696 { 1697 const char kDescription[] = "Empty data frame"; 1698 const unsigned char kV3FrameData[] = { // Also applies for V2. 1699 0x00, 0x00, 0x00, 0x01, 1700 0x00, 0x00, 0x00, 0x00, 1701 }; 1702 const unsigned char kV4FrameData[] = { 1703 0x00, 0x08, 0x00, 0x00, 1704 0x00, 0x00, 0x00, 0x01, 1705 }; 1706 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 1707 1, "", 0, DATA_FLAG_NONE)); 1708 if (IsSpdy4()) { 1709 CompareFrame( 1710 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1711 } else { 1712 CompareFrame( 1713 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1714 } 1715 } 1716 1717 { 1718 const char kDescription[] = "Data frame with max stream ID"; 1719 const unsigned char kV3FrameData[] = { // Also applies for V2. 1720 0x7f, 0xff, 0xff, 0xff, 1721 0x01, 0x00, 0x00, 0x05, 1722 'h', 'e', 'l', 'l', 1723 'o' 1724 }; 1725 const unsigned char kV4FrameData[] = { 1726 0x00, 0x0d, 0x00, 0x01, 1727 0x7f, 0xff, 0xff, 0xff, 1728 'h', 'e', 'l', 'l', 1729 'o' 1730 }; 1731 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 1732 0x7fffffff, "hello", 5, DATA_FLAG_FIN)); 1733 if (IsSpdy4()) { 1734 CompareFrame( 1735 kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1736 } else { 1737 CompareFrame( 1738 kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1739 } 1740 } 1741 1742 if (!IsSpdy4()) { 1743 // This test does not apply to SPDY 4 because the max frame size is smaller 1744 // than 4MB. 1745 const char kDescription[] = "Large data frame"; 1746 const int kDataSize = 4 * 1024 * 1024; // 4 MB 1747 const string kData(kDataSize, 'A'); 1748 const unsigned char kFrameHeader[] = { 1749 0x00, 0x00, 0x00, 0x01, 1750 0x01, 0x40, 0x00, 0x00, 1751 }; 1752 1753 const int kFrameSize = arraysize(kFrameHeader) + kDataSize; 1754 scoped_ptr<unsigned char[]> expected_frame_data( 1755 new unsigned char[kFrameSize]); 1756 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader)); 1757 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize); 1758 1759 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 1760 1, kData.data(), kData.size(), DATA_FLAG_FIN)); 1761 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize); 1762 } 1763} 1764 1765TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) { 1766 SpdyFramer framer(spdy_version_); 1767 framer.set_enable_compression(false); 1768 1769 { 1770 const char kDescription[] = "SYN_STREAM frame, lowest pri, slot 2, no FIN"; 1771 1772 SpdyHeaderBlock headers; 1773 headers["bar"] = "foo"; 1774 headers["foo"] = "bar"; 1775 1776 const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0; 1777 const unsigned char kCre = IsSpdy2() ? 0 : 2; 1778 const unsigned char kV2FrameData[] = { 1779 0x80, spdy_version_ch_, 0x00, 0x01, 1780 0x00, 0x00, 0x00, 0x20, 1781 0x00, 0x00, 0x00, 0x01, 1782 0x00, 0x00, 0x00, 0x00, 1783 kPri, 0x00, 0x00, 0x02, 1784 0x00, 0x03, 'b', 'a', 1785 'r', 0x00, 0x03, 'f', 1786 'o', 'o', 0x00, 0x03, 1787 'f', 'o', 'o', 0x00, 1788 0x03, 'b', 'a', 'r' 1789 }; 1790 const unsigned char kV3FrameData[] = { 1791 0x80, spdy_version_ch_, 0x00, 0x01, 1792 0x00, 0x00, 0x00, 0x2a, 1793 0x00, 0x00, 0x00, 0x01, 1794 0x00, 0x00, 0x00, 0x00, 1795 kPri, kCre, 0x00, 0x00, 1796 0x00, 0x02, 0x00, 0x00, 1797 0x00, 0x03, 'b', 'a', 1798 'r', 0x00, 0x00, 0x00, 1799 0x03, 'f', 'o', 'o', 1800 0x00, 0x00, 0x00, 0x03, 1801 'f', 'o', 'o', 0x00, 1802 0x00, 0x00, 0x03, 'b', 1803 'a', 'r' 1804 }; 1805 const unsigned char kV4FrameData[] = { 1806 0x00, 0x2e, 0x01, 0x00, 1807 0x00, 0x00, 0x00, 0x01, 1808 0x00, 0x00, 0x00, 0x00, 1809 kPri, kCre, 0x00, 0x00, 1810 0x00, 0x02, 0x00, 0x00, 1811 0x00, 0x03, 'b', 'a', 1812 'r', 0x00, 0x00, 0x00, 1813 0x03, 'f', 'o', 'o', 1814 0x00, 0x00, 0x00, 0x03, 1815 'f', 'o', 'o', 0x00, 1816 0x00, 0x00, 0x03, 'b', 1817 'a', 'r' 1818 }; 1819 scoped_ptr<SpdyFrame> frame( 1820 framer.CreateSynStream(1, // stream id 1821 0, // associated stream id 1822 framer.GetLowestPriority(), 1823 kCre, // credential slot 1824 CONTROL_FLAG_NONE, 1825 false, // compress 1826 &headers)); 1827 if (IsSpdy2()) { 1828 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 1829 } else if (IsSpdy3()) { 1830 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1831 } else { 1832 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1833 } 1834 } 1835 1836 { 1837 const char kDescription[] = 1838 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, " 1839 "max stream ID"; 1840 1841 SpdyHeaderBlock headers; 1842 headers[std::string()] = "foo"; 1843 headers["foo"] = "bar"; 1844 1845 const unsigned char kV2FrameData[] = { 1846 0x80, spdy_version_ch_, 0x00, 0x01, 1847 0x01, 0x00, 0x00, 0x1D, 1848 0x7f, 0xff, 0xff, 0xff, 1849 0x7f, 0xff, 0xff, 0xff, 1850 0x00, 0x00, 0x00, 0x02, 1851 0x00, 0x00, 0x00, 0x03, 1852 'f', 'o', 'o', 0x00, 1853 0x03, 'f', 'o', 'o', 1854 0x00, 0x03, 'b', 'a', 1855 'r' 1856 }; 1857 const unsigned char kV3FrameData[] = { 1858 0x80, spdy_version_ch_, 0x00, 0x01, 1859 0x01, 0x00, 0x00, 0x27, 1860 0x7f, 0xff, 0xff, 0xff, 1861 0x7f, 0xff, 0xff, 0xff, 1862 0x00, 0x00, 0x00, 0x00, 1863 0x00, 0x02, 0x00, 0x00, 1864 0x00, 0x00, 0x00, 0x00, 1865 0x00, 0x03, 'f', 'o', 1866 'o', 0x00, 0x00, 0x00, 1867 0x03, 'f', 'o', 'o', 1868 0x00, 0x00, 0x00, 0x03, 1869 'b', 'a', 'r' 1870 }; 1871 const unsigned char kV4FrameData[] = { 1872 0x00, 0x2b, 0x01, 0x01, 1873 0x7f, 0xff, 0xff, 0xff, 1874 0x7f, 0xff, 0xff, 0xff, 1875 0x00, 0x00, 0x00, 0x00, 1876 0x00, 0x02, 0x00, 0x00, 1877 0x00, 0x00, 0x00, 0x00, 1878 0x00, 0x03, 'f', 'o', 1879 'o', 0x00, 0x00, 0x00, 1880 0x03, 'f', 'o', 'o', 1881 0x00, 0x00, 0x00, 0x03, 1882 'b', 'a', 'r' 1883 }; 1884 scoped_ptr<SpdyFrame> frame( 1885 framer.CreateSynStream(0x7fffffff, // stream id 1886 0x7fffffff, // associated stream id 1887 framer.GetHighestPriority(), 1888 0, // credential slot 1889 CONTROL_FLAG_FIN, 1890 false, // compress 1891 &headers)); 1892 if (IsSpdy2()) { 1893 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 1894 } else if (IsSpdy3()) { 1895 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1896 } else { 1897 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1898 } 1899 } 1900 1901 { 1902 const char kDescription[] = 1903 "SYN_STREAM frame with a 0-length header val, high pri, FIN, " 1904 "max stream ID"; 1905 1906 SpdyHeaderBlock headers; 1907 headers["bar"] = "foo"; 1908 headers["foo"] = ""; 1909 1910 const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20; 1911 const unsigned char kV2FrameData[] = { 1912 0x80, spdy_version_ch_, 0x00, 0x01, 1913 0x01, 0x00, 0x00, 0x1D, 1914 0x7f, 0xff, 0xff, 0xff, 1915 0x7f, 0xff, 0xff, 0xff, 1916 kPri, 0x00, 0x00, 0x02, 1917 0x00, 0x03, 'b', 'a', 1918 'r', 0x00, 0x03, 'f', 1919 'o', 'o', 0x00, 0x03, 1920 'f', 'o', 'o', 0x00, 1921 0x00 1922 }; 1923 const unsigned char kV3FrameData[] = { 1924 0x80, spdy_version_ch_, 0x00, 0x01, 1925 0x01, 0x00, 0x00, 0x27, 1926 0x7f, 0xff, 0xff, 0xff, 1927 0x7f, 0xff, 0xff, 0xff, 1928 kPri, 0x00, 0x00, 0x00, 1929 0x00, 0x02, 0x00, 0x00, 1930 0x00, 0x03, 'b', 'a', 1931 'r', 0x00, 0x00, 0x00, 1932 0x03, 'f', 'o', 'o', 1933 0x00, 0x00, 0x00, 0x03, 1934 'f', 'o', 'o', 0x00, 1935 0x00, 0x00, 0x00 1936 }; 1937 const unsigned char kV4FrameData[] = { 1938 0x00, 0x2b, 0x01, 0x01, 1939 0x7f, 0xff, 0xff, 0xff, 1940 0x7f, 0xff, 0xff, 0xff, 1941 kPri, 0x00, 0x00, 0x00, 1942 0x00, 0x02, 0x00, 0x00, 1943 0x00, 0x03, 'b', 'a', 1944 'r', 0x00, 0x00, 0x00, 1945 0x03, 'f', 'o', 'o', 1946 0x00, 0x00, 0x00, 0x03, 1947 'f', 'o', 'o', 0x00, 1948 0x00, 0x00, 0x00 1949 }; 1950 scoped_ptr<SpdyFrame> frame( 1951 framer.CreateSynStream(0x7fffffff, // stream id 1952 0x7fffffff, // associated stream id 1953 1, // priority 1954 0, // credential slot 1955 CONTROL_FLAG_FIN, 1956 false, // compress 1957 &headers)); 1958 if (IsSpdy2()) { 1959 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 1960 } else if (IsSpdy3()) { 1961 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 1962 } else { 1963 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 1964 } 1965 } 1966} 1967 1968// TODO(phajdan.jr): Clean up after we no longer need 1969// to workaround http://crbug.com/139744. 1970#if !defined(USE_SYSTEM_ZLIB) 1971TEST_P(SpdyFramerTest, CreateSynStreamCompressed) { 1972 SpdyFramer framer(spdy_version_); 1973 framer.set_enable_compression(true); 1974 1975 { 1976 const char kDescription[] = 1977 "SYN_STREAM frame, low pri, no FIN"; 1978 1979 SpdyHeaderBlock headers; 1980 headers["bar"] = "foo"; 1981 headers["foo"] = "bar"; 1982 1983 const SpdyPriority priority = IsSpdy2() ? 2 : 4; 1984 const unsigned char kV2FrameData[] = { 1985 0x80, spdy_version_ch_, 0x00, 0x01, 1986 0x00, 0x00, 0x00, 0x36, 1987 0x00, 0x00, 0x00, 0x01, 1988 0x00, 0x00, 0x00, 0x00, 1989 0x80, 0x00, 0x38, 0xea, 1990 0xdf, 0xa2, 0x51, 0xb2, 1991 0x62, 0x60, 0x62, 0x60, 1992 0x4e, 0x4a, 0x2c, 0x62, 1993 0x60, 0x06, 0x08, 0xa0, 1994 0xb4, 0xfc, 0x7c, 0x80, 1995 0x00, 0x62, 0x60, 0x4e, 1996 0xcb, 0xcf, 0x67, 0x60, 1997 0x06, 0x08, 0xa0, 0xa4, 1998 0xc4, 0x22, 0x80, 0x00, 1999 0x02, 0x00, 0x00, 0x00, 2000 0xff, 0xff, 2001 }; 2002 const unsigned char kV3FrameData[] = { 2003 0x80, spdy_version_ch_, 0x00, 0x01, 2004 0x00, 0x00, 0x00, 0x37, 2005 0x00, 0x00, 0x00, 0x01, 2006 0x00, 0x00, 0x00, 0x00, 2007 0x80, 0x00, 0x38, 0xEA, 2008 0xE3, 0xC6, 0xA7, 0xC2, 2009 0x02, 0xE5, 0x0E, 0x50, 2010 0xC2, 0x4B, 0x4A, 0x04, 2011 0xE5, 0x0B, 0x66, 0x80, 2012 0x00, 0x4A, 0xCB, 0xCF, 2013 0x07, 0x08, 0x20, 0x10, 2014 0x95, 0x96, 0x9F, 0x0F, 2015 0xA2, 0x00, 0x02, 0x28, 2016 0x29, 0xB1, 0x08, 0x20, 2017 0x80, 0x00, 0x00, 0x00, 2018 0x00, 0xFF, 0xFF, 2019 }; 2020 const unsigned char kV4FrameData[] = { 2021 0x00, 0x3b, 0x01, 0x00, 2022 0x00, 0x00, 0x00, 0x01, 2023 0x00, 0x00, 0x00, 0x00, 2024 0x80, 0x00, 0x38, 0xea, 2025 0xe3, 0xc6, 0xa7, 0xc2, 2026 0x02, 0xe5, 0x0e, 0x50, 2027 0xc2, 0x4b, 0x4a, 0x04, 2028 0xe5, 0x0b, 0x66, 0x80, 2029 0x00, 0x4a, 0xcb, 0xcf, 2030 0x07, 0x08, 0x20, 0x10, 2031 0x95, 0x96, 0x9f, 0x0f, 2032 0xa2, 0x00, 0x02, 0x28, 2033 0x29, 0xb1, 0x08, 0x20, 2034 0x80, 0x00, 0x00, 0x00, 2035 0x00, 0xff, 0xff, 2036 }; 2037 scoped_ptr<SpdyFrame> frame( 2038 framer.CreateSynStream(1, // stream id 2039 0, // associated stream id 2040 priority, 2041 0, // credential slot 2042 CONTROL_FLAG_NONE, 2043 true, // compress 2044 &headers)); 2045 if (IsSpdy2()) { 2046 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2047 } else if (IsSpdy3()) { 2048 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2049 } else { 2050 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2051 } 2052 } 2053} 2054#endif // !defined(USE_SYSTEM_ZLIB) 2055 2056TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) { 2057 SpdyFramer framer(spdy_version_); 2058 framer.set_enable_compression(false); 2059 2060 { 2061 const char kDescription[] = "SYN_REPLY frame, no FIN"; 2062 2063 SpdyHeaderBlock headers; 2064 headers["bar"] = "foo"; 2065 headers["foo"] = "bar"; 2066 2067 const unsigned char kV2FrameData[] = { 2068 0x80, spdy_version_ch_, 0x00, 0x02, 2069 0x00, 0x00, 0x00, 0x1C, 2070 0x00, 0x00, 0x00, 0x01, 2071 0x00, 0x00, 0x00, 0x02, 2072 0x00, 0x03, 'b', 'a', 2073 'r', 0x00, 0x03, 'f', 2074 'o', 'o', 0x00, 0x03, 2075 'f', 'o', 'o', 0x00, 2076 0x03, 'b', 'a', 'r' 2077 }; 2078 const unsigned char kV3FrameData[] = { 2079 0x80, spdy_version_ch_, 0x00, 0x02, 2080 0x00, 0x00, 0x00, 0x24, 2081 0x00, 0x00, 0x00, 0x01, 2082 0x00, 0x00, 0x00, 0x02, 2083 0x00, 0x00, 0x00, 0x03, 2084 'b', 'a', 'r', 0x00, 2085 0x00, 0x00, 0x03, 'f', 2086 'o', 'o', 0x00, 0x00, 2087 0x00, 0x03, 'f', 'o', 2088 'o', 0x00, 0x00, 0x00, 2089 0x03, 'b', 'a', 'r' 2090 }; 2091 const unsigned char kV4FrameData[] = { 2092 0x00, 0x28, 0x02, 0x00, 2093 0x00, 0x00, 0x00, 0x01, 2094 0x00, 0x00, 0x00, 0x02, 2095 0x00, 0x00, 0x00, 0x03, 2096 'b', 'a', 'r', 0x00, 2097 0x00, 0x00, 0x03, 'f', 2098 'o', 'o', 0x00, 0x00, 2099 0x00, 0x03, 'f', 'o', 2100 'o', 0x00, 0x00, 0x00, 2101 0x03, 'b', 'a', 'r' 2102 }; 2103 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 2104 1, CONTROL_FLAG_NONE, false, &headers)); 2105 if (IsSpdy2()) { 2106 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2107 } else if (IsSpdy3()) { 2108 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2109 } else { 2110 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2111 } 2112 } 2113 2114 { 2115 const char kDescription[] = 2116 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID"; 2117 2118 SpdyHeaderBlock headers; 2119 headers[std::string()] = "foo"; 2120 headers["foo"] = "bar"; 2121 2122 const unsigned char kV2FrameData[] = { 2123 0x80, spdy_version_ch_, 0x00, 0x02, 2124 0x01, 0x00, 0x00, 0x19, 2125 0x7f, 0xff, 0xff, 0xff, 2126 0x00, 0x00, 0x00, 0x02, 2127 0x00, 0x00, 0x00, 0x03, 2128 'f', 'o', 'o', 0x00, 2129 0x03, 'f', 'o', 'o', 2130 0x00, 0x03, 'b', 'a', 2131 'r' 2132 }; 2133 const unsigned char kV3FrameData[] = { 2134 0x80, spdy_version_ch_, 0x00, 0x02, 2135 0x01, 0x00, 0x00, 0x21, 2136 0x7f, 0xff, 0xff, 0xff, 2137 0x00, 0x00, 0x00, 0x02, 2138 0x00, 0x00, 0x00, 0x00, 2139 0x00, 0x00, 0x00, 0x03, 2140 'f', 'o', 'o', 0x00, 2141 0x00, 0x00, 0x03, 'f', 2142 'o', 'o', 0x00, 0x00, 2143 0x00, 0x03, 'b', 'a', 2144 'r' 2145 }; 2146 const unsigned char kV4FrameData[] = { 2147 0x00, 0x25, 0x02, 0x01, 2148 0x7f, 0xff, 0xff, 0xff, 2149 0x00, 0x00, 0x00, 0x02, 2150 0x00, 0x00, 0x00, 0x00, 2151 0x00, 0x00, 0x00, 0x03, 2152 'f', 'o', 'o', 0x00, 2153 0x00, 0x00, 0x03, 'f', 2154 'o', 'o', 0x00, 0x00, 2155 0x00, 0x03, 'b', 'a', 2156 'r' 2157 }; 2158 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 2159 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 2160 if (IsSpdy2()) { 2161 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2162 } else if (IsSpdy3()) { 2163 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2164 } else { 2165 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2166 } 2167 } 2168 2169 { 2170 const char kDescription[] = 2171 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID"; 2172 2173 SpdyHeaderBlock headers; 2174 headers["bar"] = "foo"; 2175 headers["foo"] = ""; 2176 2177 const unsigned char kV2FrameData[] = { 2178 0x80, spdy_version_ch_, 0x00, 0x02, 2179 0x01, 0x00, 0x00, 0x19, 2180 0x7f, 0xff, 0xff, 0xff, 2181 0x00, 0x00, 0x00, 0x02, 2182 0x00, 0x03, 'b', 'a', 2183 'r', 0x00, 0x03, 'f', 2184 'o', 'o', 0x00, 0x03, 2185 'f', 'o', 'o', 0x00, 2186 0x00 2187 }; 2188 const unsigned char kV3FrameData[] = { 2189 0x80, spdy_version_ch_, 0x00, 0x02, 2190 0x01, 0x00, 0x00, 0x21, 2191 0x7f, 0xff, 0xff, 0xff, 2192 0x00, 0x00, 0x00, 0x02, 2193 0x00, 0x00, 0x00, 0x03, 2194 'b', 'a', 'r', 0x00, 2195 0x00, 0x00, 0x03, 'f', 2196 'o', 'o', 0x00, 0x00, 2197 0x00, 0x03, 'f', 'o', 2198 'o', 0x00, 0x00, 0x00, 2199 0x00 2200 }; 2201 const unsigned char kV4FrameData[] = { 2202 0x00, 0x25, 0x02, 0x01, 2203 0x7f, 0xff, 0xff, 0xff, 2204 0x00, 0x00, 0x00, 0x02, 2205 0x00, 0x00, 0x00, 0x03, 2206 'b', 'a', 'r', 0x00, 2207 0x00, 0x00, 0x03, 'f', 2208 'o', 'o', 0x00, 0x00, 2209 0x00, 0x03, 'f', 'o', 2210 'o', 0x00, 0x00, 0x00, 2211 0x00 2212 }; 2213 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 2214 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 2215 if (IsSpdy2()) { 2216 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2217 } else if (IsSpdy3()) { 2218 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2219 } else { 2220 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2221 } 2222 } 2223} 2224 2225// TODO(phajdan.jr): Clean up after we no longer need 2226// to workaround http://crbug.com/139744. 2227#if !defined(USE_SYSTEM_ZLIB) 2228TEST_P(SpdyFramerTest, CreateSynReplyCompressed) { 2229 SpdyFramer framer(spdy_version_); 2230 framer.set_enable_compression(true); 2231 2232 { 2233 const char kDescription[] = "SYN_REPLY frame, no FIN"; 2234 2235 SpdyHeaderBlock headers; 2236 headers["bar"] = "foo"; 2237 headers["foo"] = "bar"; 2238 2239 const unsigned char kV2FrameData[] = { 2240 0x80, spdy_version_ch_, 0x00, 0x02, 2241 0x00, 0x00, 0x00, 0x32, 2242 0x00, 0x00, 0x00, 0x01, 2243 0x00, 0x00, 0x38, 0xea, 2244 0xdf, 0xa2, 0x51, 0xb2, 2245 0x62, 0x60, 0x62, 0x60, 2246 0x4e, 0x4a, 0x2c, 0x62, 2247 0x60, 0x06, 0x08, 0xa0, 2248 0xb4, 0xfc, 0x7c, 0x80, 2249 0x00, 0x62, 0x60, 0x4e, 2250 0xcb, 0xcf, 0x67, 0x60, 2251 0x06, 0x08, 0xa0, 0xa4, 2252 0xc4, 0x22, 0x80, 0x00, 2253 0x02, 0x00, 0x00, 0x00, 2254 0xff, 0xff, 2255 }; 2256 const unsigned char kV3FrameData[] = { 2257 0x80, spdy_version_ch_, 0x00, 0x02, 2258 0x00, 0x00, 0x00, 0x31, 2259 0x00, 0x00, 0x00, 0x01, 2260 0x38, 0xea, 0xe3, 0xc6, 2261 0xa7, 0xc2, 0x02, 0xe5, 2262 0x0e, 0x50, 0xc2, 0x4b, 2263 0x4a, 0x04, 0xe5, 0x0b, 2264 0x66, 0x80, 0x00, 0x4a, 2265 0xcb, 0xcf, 0x07, 0x08, 2266 0x20, 0x10, 0x95, 0x96, 2267 0x9f, 0x0f, 0xa2, 0x00, 2268 0x02, 0x28, 0x29, 0xb1, 2269 0x08, 0x20, 0x80, 0x00, 2270 0x00, 0x00, 0x00, 0xff, 2271 0xff, 2272 }; 2273 const unsigned char kV4FrameData[] = { 2274 0x00, 0x35, 0x02, 0x00, 2275 0x00, 0x00, 0x00, 0x01, 2276 0x38, 0xea, 0xe3, 0xc6, 2277 0xa7, 0xc2, 0x02, 0xe5, 2278 0x0e, 0x50, 0xc2, 0x4b, 2279 0x4a, 0x04, 0xe5, 0x0b, 2280 0x66, 0x80, 0x00, 0x4a, 2281 0xcb, 0xcf, 0x07, 0x08, 2282 0x20, 0x10, 0x95, 0x96, 2283 0x9f, 0x0f, 0xa2, 0x00, 2284 0x02, 0x28, 0x29, 0xb1, 2285 0x08, 0x20, 0x80, 0x00, 2286 0x00, 0x00, 0x00, 0xff, 2287 0xff, 2288 }; 2289 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 2290 1, CONTROL_FLAG_NONE, true, &headers)); 2291 if (IsSpdy2()) { 2292 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2293 } else if (IsSpdy3()) { 2294 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2295 } else { 2296 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2297 } 2298 } 2299} 2300#endif // !defined(USE_SYSTEM_ZLIB) 2301 2302TEST_P(SpdyFramerTest, CreateRstStream) { 2303 SpdyFramer framer(spdy_version_); 2304 2305 { 2306 const char kDescription[] = "RST_STREAM frame"; 2307 const unsigned char kV3FrameData[] = { // Also applies for V2. 2308 0x80, spdy_version_ch_, 0x00, 0x03, 2309 0x00, 0x00, 0x00, 0x08, 2310 0x00, 0x00, 0x00, 0x01, 2311 0x00, 0x00, 0x00, 0x01, 2312 }; 2313 const unsigned char kV4FrameData[] = { 2314 0x00, 0x0c, 0x03, 0x00, 2315 0x00, 0x00, 0x00, 0x01, 2316 0x00, 0x00, 0x00, 0x01, 2317 }; 2318 scoped_ptr<SpdyFrame> frame( 2319 framer.CreateRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 2320 if (IsSpdy4()) { 2321 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2322 } else { 2323 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2324 } 2325 } 2326 2327 { 2328 const char kDescription[] = "RST_STREAM frame with max stream ID"; 2329 const unsigned char kV3FrameData[] = { // Also applies for V2. 2330 0x80, spdy_version_ch_, 0x00, 0x03, 2331 0x00, 0x00, 0x00, 0x08, 2332 0x7f, 0xff, 0xff, 0xff, 2333 0x00, 0x00, 0x00, 0x01, 2334 }; 2335 const unsigned char kV4FrameData[] = { 2336 0x00, 0x0c, 0x03, 0x00, 2337 0x7f, 0xff, 0xff, 0xff, 2338 0x00, 0x00, 0x00, 0x01, 2339 }; 2340 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream( 2341 0x7FFFFFFF, RST_STREAM_PROTOCOL_ERROR)); 2342 if (IsSpdy4()) { 2343 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2344 } else { 2345 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2346 } 2347 } 2348 2349 { 2350 const char kDescription[] = "RST_STREAM frame with max status code"; 2351 const unsigned char kV3FrameData[] = { // Also applies for V2. 2352 0x80, spdy_version_ch_, 0x00, 0x03, 2353 0x00, 0x00, 0x00, 0x08, 2354 0x7f, 0xff, 0xff, 0xff, 2355 0x00, 0x00, 0x00, 0x06, 2356 }; 2357 const unsigned char kV4FrameData[] = { 2358 0x00, 0x0c, 0x03, 0x00, 2359 0x7f, 0xff, 0xff, 0xff, 2360 0x00, 0x00, 0x00, 0x06, 2361 }; 2362 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream( 2363 0x7FFFFFFF, RST_STREAM_INTERNAL_ERROR)); 2364 if (IsSpdy4()) { 2365 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2366 } else { 2367 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2368 } 2369 } 2370} 2371 2372TEST_P(SpdyFramerTest, CreateSettings) { 2373 SpdyFramer framer(spdy_version_); 2374 2375 { 2376 const char kDescription[] = "Network byte order SETTINGS frame"; 2377 2378 uint32 kValue = 0x0a0b0c0d; 2379 SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01); 2380 SpdySettingsIds kId = static_cast<SpdySettingsIds>(0x020304); 2381 2382 SettingsMap settings; 2383 settings[kId] = SettingsFlagsAndValue(kFlags, kValue); 2384 2385 EXPECT_EQ(kFlags, settings[kId].first); 2386 EXPECT_EQ(kValue, settings[kId].second); 2387 2388 const unsigned char kV2FrameData[] = { 2389 0x80, spdy_version_ch_, 0x00, 0x04, 2390 0x00, 0x00, 0x00, 0x0c, 2391 0x00, 0x00, 0x00, 0x01, 2392 0x04, 0x03, 0x02, 0x01, 2393 0x0a, 0x0b, 0x0c, 0x0d, 2394 }; 2395 const unsigned char kV3FrameData[] = { 2396 0x80, spdy_version_ch_, 0x00, 0x04, 2397 0x00, 0x00, 0x00, 0x0c, 2398 0x00, 0x00, 0x00, 0x01, 2399 0x01, 0x02, 0x03, 0x04, 2400 0x0a, 0x0b, 0x0c, 0x0d, 2401 }; 2402 const unsigned char kV4FrameData[] = { 2403 0x00, 0x14, 0x04, 0x00, 2404 0x00, 0x00, 0x00, 0x00, 2405 0x00, 0x00, 0x00, 0x01, 2406 0x01, 0x02, 0x03, 0x04, 2407 0x0a, 0x0b, 0x0c, 0x0d, 2408 }; 2409 2410 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings)); 2411 if (IsSpdy2()) { 2412 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2413 } else if (IsSpdy3()) { 2414 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2415 } else { 2416 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2417 } 2418 } 2419 2420 { 2421 const char kDescription[] = "Basic SETTINGS frame"; 2422 2423 SettingsMap settings; 2424 AddSpdySettingFromWireFormat( 2425 &settings, 0x00000000, 0x00000001); // 1st Setting 2426 AddSpdySettingFromWireFormat( 2427 &settings, 0x01000001, 0x00000002); // 2nd Setting 2428 AddSpdySettingFromWireFormat( 2429 &settings, 0x02000002, 0x00000003); // 3rd Setting 2430 AddSpdySettingFromWireFormat( 2431 &settings, 0x03000003, 0xff000004); // 4th Setting 2432 2433 const unsigned char kV3FrameData[] = { // Also applies for V2. 2434 0x80, spdy_version_ch_, 0x00, 0x04, 2435 0x00, 0x00, 0x00, 0x24, 2436 0x00, 0x00, 0x00, 0x04, 2437 0x00, 0x00, 0x00, 0x00, // 1st Setting 2438 0x00, 0x00, 0x00, 0x01, 2439 0x01, 0x00, 0x00, 0x01, // 2nd Setting 2440 0x00, 0x00, 0x00, 0x02, 2441 0x02, 0x00, 0x00, 0x02, // 3rd Setting 2442 0x00, 0x00, 0x00, 0x03, 2443 0x03, 0x00, 0x00, 0x03, // 4th Setting 2444 0xff, 0x00, 0x00, 0x04, 2445 }; 2446 const unsigned char kV4FrameData[] = { 2447 0x00, 0x2c, 0x04, 0x00, 2448 0x00, 0x00, 0x00, 0x00, 2449 0x00, 0x00, 0x00, 0x04, 2450 0x00, 0x00, 0x00, 0x00, // 1st Setting 2451 0x00, 0x00, 0x00, 0x01, 2452 0x01, 0x00, 0x00, 0x01, // 2nd Setting 2453 0x00, 0x00, 0x00, 0x02, 2454 0x02, 0x00, 0x00, 0x02, // 3rd Setting 2455 0x00, 0x00, 0x00, 0x03, 2456 0x03, 0x00, 0x00, 0x03, // 4th Setting 2457 0xff, 0x00, 0x00, 0x04, 2458 }; 2459 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings)); 2460 if (IsSpdy4()) { 2461 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2462 } else { 2463 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2464 } 2465 } 2466 2467 { 2468 const char kDescription[] = "Empty SETTINGS frame"; 2469 2470 SettingsMap settings; 2471 2472 const unsigned char kV3FrameData[] = { // Also applies for V2. 2473 0x80, spdy_version_ch_, 0x00, 0x04, 2474 0x00, 0x00, 0x00, 0x04, 2475 0x00, 0x00, 0x00, 0x00, 2476 }; 2477 const unsigned char kV4FrameData[] = { 2478 0x00, 0x0c, 0x04, 0x00, 2479 0x00, 0x00, 0x00, 0x00, 2480 0x00, 0x00, 0x00, 0x00, 2481 }; 2482 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings)); 2483 if (IsSpdy4()) { 2484 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2485 } else { 2486 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2487 } 2488 } 2489} 2490 2491TEST_P(SpdyFramerTest, CreatePingFrame) { 2492 SpdyFramer framer(spdy_version_); 2493 2494 { 2495 const char kDescription[] = "PING frame"; 2496 const unsigned char kV3FrameData[] = { // Also applies for V2. 2497 0x80, spdy_version_ch_, 0x00, 0x06, 2498 0x00, 0x00, 0x00, 0x04, 2499 0x12, 0x34, 0x56, 0x78, 2500 }; 2501 const unsigned char kV4FrameData[] = { 2502 0x00, 0x0c, 0x06, 0x00, 2503 0x00, 0x00, 0x00, 0x00, 2504 0x12, 0x34, 0x56, 0x78, 2505 }; 2506 scoped_ptr<SpdyFrame> frame(framer.CreatePingFrame(0x12345678u)); 2507 if (IsSpdy4()) { 2508 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2509 } else { 2510 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2511 } 2512 } 2513} 2514 2515TEST_P(SpdyFramerTest, CreateGoAway) { 2516 SpdyFramer framer(spdy_version_); 2517 2518 { 2519 const char kDescription[] = "GOAWAY frame"; 2520 const unsigned char kV2FrameData[] = { 2521 0x80, spdy_version_ch_, 0x00, 0x07, 2522 0x00, 0x00, 0x00, 0x04, 2523 0x00, 0x00, 0x00, 0x00, 2524 }; 2525 const unsigned char kV3FrameData[] = { 2526 0x80, spdy_version_ch_, 0x00, 0x07, 2527 0x00, 0x00, 0x00, 0x08, 2528 0x00, 0x00, 0x00, 0x00, 2529 0x00, 0x00, 0x00, 0x00, 2530 }; 2531 const unsigned char kV4FrameData[] = { 2532 0x00, 0x10, 0x07, 0x00, 2533 0x00, 0x00, 0x00, 0x00, 2534 0x00, 0x00, 0x00, 0x00, 2535 0x00, 0x00, 0x00, 0x00, 2536 }; 2537 scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0, GOAWAY_OK)); 2538 if (IsSpdy2()) { 2539 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2540 } else if (IsSpdy3()) { 2541 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2542 } else { 2543 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2544 } 2545 } 2546 2547 { 2548 const char kDescription[] = "GOAWAY frame with max stream ID, status"; 2549 const unsigned char kV2FrameData[] = { 2550 0x80, spdy_version_ch_, 0x00, 0x07, 2551 0x00, 0x00, 0x00, 0x04, 2552 0x7f, 0xff, 0xff, 0xff, 2553 }; 2554 const unsigned char kV3FrameData[] = { 2555 0x80, spdy_version_ch_, 0x00, 0x07, 2556 0x00, 0x00, 0x00, 0x08, 2557 0x7f, 0xff, 0xff, 0xff, 2558 0x00, 0x00, 0x00, 0x02, 2559 }; 2560 const unsigned char kV4FrameData[] = { 2561 0x00, 0x10, 0x07, 0x00, 2562 0x00, 0x00, 0x00, 0x00, 2563 0x7f, 0xff, 0xff, 0xff, 2564 0x00, 0x00, 0x00, 0x02, 2565 }; 2566 scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0x7FFFFFFF, 2567 GOAWAY_INTERNAL_ERROR)); 2568 if (IsSpdy2()) { 2569 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2570 } else if (IsSpdy3()) { 2571 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2572 } else { 2573 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2574 } 2575 } 2576} 2577 2578TEST_P(SpdyFramerTest, CreateHeadersUncompressed) { 2579 SpdyFramer framer(spdy_version_); 2580 framer.set_enable_compression(false); 2581 2582 { 2583 const char kDescription[] = "HEADERS frame, no FIN"; 2584 2585 SpdyHeaderBlock headers; 2586 headers["bar"] = "foo"; 2587 headers["foo"] = "bar"; 2588 2589 const unsigned char kV2FrameData[] = { 2590 0x80, spdy_version_ch_, 0x00, 0x08, 2591 0x00, 0x00, 0x00, 0x1C, 2592 0x00, 0x00, 0x00, 0x01, 2593 0x00, 0x00, 0x00, 0x02, 2594 0x00, 0x03, 'b', 'a', 2595 'r', 0x00, 0x03, 'f', 2596 'o', 'o', 0x00, 0x03, 2597 'f', 'o', 'o', 0x00, 2598 0x03, 'b', 'a', 'r' 2599 }; 2600 const unsigned char kV3FrameData[] = { 2601 0x80, spdy_version_ch_, 0x00, 0x08, 2602 0x00, 0x00, 0x00, 0x24, 2603 0x00, 0x00, 0x00, 0x01, 2604 0x00, 0x00, 0x00, 0x02, 2605 0x00, 0x00, 0x00, 0x03, 2606 'b', 'a', 'r', 0x00, 2607 0x00, 0x00, 0x03, 'f', 2608 'o', 'o', 0x00, 0x00, 2609 0x00, 0x03, 'f', 'o', 2610 'o', 0x00, 0x00, 0x00, 2611 0x03, 'b', 'a', 'r' 2612 }; 2613 const unsigned char kV4FrameData[] = { 2614 0x00, 0x28, 0x08, 0x00, 2615 0x00, 0x00, 0x00, 0x01, 2616 0x00, 0x00, 0x00, 0x02, 2617 0x00, 0x00, 0x00, 0x03, 2618 'b', 'a', 'r', 0x00, 2619 0x00, 0x00, 0x03, 'f', 2620 'o', 'o', 0x00, 0x00, 2621 0x00, 0x03, 'f', 'o', 2622 'o', 0x00, 0x00, 0x00, 2623 0x03, 'b', 'a', 'r' 2624 }; 2625 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 2626 1, CONTROL_FLAG_NONE, false, &headers)); 2627 if (IsSpdy2()) { 2628 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2629 } else if (IsSpdy3()) { 2630 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2631 } else { 2632 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2633 } 2634 } 2635 2636 { 2637 const char kDescription[] = 2638 "HEADERS frame with a 0-length header name, FIN, max stream ID"; 2639 2640 SpdyHeaderBlock headers; 2641 headers[std::string()] = "foo"; 2642 headers["foo"] = "bar"; 2643 2644 const unsigned char kV2FrameData[] = { 2645 0x80, spdy_version_ch_, 0x00, 0x08, 2646 0x01, 0x00, 0x00, 0x19, 2647 0x7f, 0xff, 0xff, 0xff, 2648 0x00, 0x00, 0x00, 0x02, 2649 0x00, 0x00, 0x00, 0x03, 2650 'f', 'o', 'o', 0x00, 2651 0x03, 'f', 'o', 'o', 2652 0x00, 0x03, 'b', 'a', 2653 'r' 2654 }; 2655 const unsigned char kV3FrameData[] = { 2656 0x80, spdy_version_ch_, 0x00, 0x08, 2657 0x01, 0x00, 0x00, 0x21, 2658 0x7f, 0xff, 0xff, 0xff, 2659 0x00, 0x00, 0x00, 0x02, 2660 0x00, 0x00, 0x00, 0x00, 2661 0x00, 0x00, 0x00, 0x03, 2662 'f', 'o', 'o', 0x00, 2663 0x00, 0x00, 0x03, 'f', 2664 'o', 'o', 0x00, 0x00, 2665 0x00, 0x03, 'b', 'a', 2666 'r' 2667 }; 2668 const unsigned char kV4FrameData[] = { 2669 0x00, 0x25, 0x08, 0x01, 2670 0x7f, 0xff, 0xff, 0xff, 2671 0x00, 0x00, 0x00, 0x02, 2672 0x00, 0x00, 0x00, 0x00, 2673 0x00, 0x00, 0x00, 0x03, 2674 'f', 'o', 'o', 0x00, 2675 0x00, 0x00, 0x03, 'f', 2676 'o', 'o', 0x00, 0x00, 2677 0x00, 0x03, 'b', 'a', 2678 'r' 2679 }; 2680 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 2681 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 2682 if (IsSpdy2()) { 2683 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2684 } else if (IsSpdy3()) { 2685 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2686 } else { 2687 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2688 } 2689 } 2690 2691 { 2692 const char kDescription[] = 2693 "HEADERS frame with a 0-length header val, FIN, max stream ID"; 2694 2695 SpdyHeaderBlock headers; 2696 headers["bar"] = "foo"; 2697 headers["foo"] = ""; 2698 2699 const unsigned char kV2FrameData[] = { 2700 0x80, spdy_version_ch_, 0x00, 0x08, 2701 0x01, 0x00, 0x00, 0x19, 2702 0x7f, 0xff, 0xff, 0xff, 2703 0x00, 0x00, 0x00, 0x02, 2704 0x00, 0x03, 'b', 'a', 2705 'r', 0x00, 0x03, 'f', 2706 'o', 'o', 0x00, 0x03, 2707 'f', 'o', 'o', 0x00, 2708 0x00 2709 }; 2710 const unsigned char kV3FrameData[] = { 2711 0x80, spdy_version_ch_, 0x00, 0x08, 2712 0x01, 0x00, 0x00, 0x21, 2713 0x7f, 0xff, 0xff, 0xff, 2714 0x00, 0x00, 0x00, 0x02, 2715 0x00, 0x00, 0x00, 0x03, 2716 'b', 'a', 'r', 0x00, 2717 0x00, 0x00, 0x03, 'f', 2718 'o', 'o', 0x00, 0x00, 2719 0x00, 0x03, 'f', 'o', 2720 'o', 0x00, 0x00, 0x00, 2721 0x00 2722 }; 2723 const unsigned char kV4FrameData[] = { 2724 0x00, 0x25, 0x08, 0x01, 2725 0x7f, 0xff, 0xff, 0xff, 2726 0x00, 0x00, 0x00, 0x02, 2727 0x00, 0x00, 0x00, 0x03, 2728 'b', 'a', 'r', 0x00, 2729 0x00, 0x00, 0x03, 'f', 2730 'o', 'o', 0x00, 0x00, 2731 0x00, 0x03, 'f', 'o', 2732 'o', 0x00, 0x00, 0x00, 2733 0x00 2734 }; 2735 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 2736 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 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)); 2743 } 2744 } 2745} 2746 2747// TODO(phajdan.jr): Clean up after we no longer need 2748// to workaround http://crbug.com/139744. 2749#if !defined(USE_SYSTEM_ZLIB) 2750TEST_P(SpdyFramerTest, CreateHeadersCompressed) { 2751 SpdyFramer framer(spdy_version_); 2752 framer.set_enable_compression(true); 2753 2754 { 2755 const char kDescription[] = "HEADERS frame, no FIN"; 2756 2757 SpdyHeaderBlock headers; 2758 headers["bar"] = "foo"; 2759 headers["foo"] = "bar"; 2760 2761 const unsigned char kV2FrameData[] = { 2762 0x80, spdy_version_ch_, 0x00, 0x08, 2763 0x00, 0x00, 0x00, 0x32, 2764 0x00, 0x00, 0x00, 0x01, 2765 0x00, 0x00, 0x38, 0xea, 2766 0xdf, 0xa2, 0x51, 0xb2, 2767 0x62, 0x60, 0x62, 0x60, 2768 0x4e, 0x4a, 0x2c, 0x62, 2769 0x60, 0x06, 0x08, 0xa0, 2770 0xb4, 0xfc, 0x7c, 0x80, 2771 0x00, 0x62, 0x60, 0x4e, 2772 0xcb, 0xcf, 0x67, 0x60, 2773 0x06, 0x08, 0xa0, 0xa4, 2774 0xc4, 0x22, 0x80, 0x00, 2775 0x02, 0x00, 0x00, 0x00, 2776 0xff, 0xff, 2777 }; 2778 const unsigned char kV3FrameData[] = { 2779 0x80, spdy_version_ch_, 0x00, 0x08, 2780 0x00, 0x00, 0x00, 0x31, 2781 0x00, 0x00, 0x00, 0x01, 2782 0x38, 0xea, 0xe3, 0xc6, 2783 0xa7, 0xc2, 0x02, 0xe5, 2784 0x0e, 0x50, 0xc2, 0x4b, 2785 0x4a, 0x04, 0xe5, 0x0b, 2786 0x66, 0x80, 0x00, 0x4a, 2787 0xcb, 0xcf, 0x07, 0x08, 2788 0x20, 0x10, 0x95, 0x96, 2789 0x9f, 0x0f, 0xa2, 0x00, 2790 0x02, 0x28, 0x29, 0xb1, 2791 0x08, 0x20, 0x80, 0x00, 2792 0x00, 0x00, 0x00, 0xff, 2793 0xff, 2794 }; 2795 const unsigned char kV4FrameData[] = { 2796 0x00, 0x35, 0x08, 0x00, 2797 0x00, 0x00, 0x00, 0x01, 2798 0x38, 0xea, 0xe3, 0xc6, 2799 0xa7, 0xc2, 0x02, 0xe5, 2800 0x0e, 0x50, 0xc2, 0x4b, 2801 0x4a, 0x04, 0xe5, 0x0b, 2802 0x66, 0x80, 0x00, 0x4a, 2803 0xcb, 0xcf, 0x07, 0x08, 2804 0x20, 0x10, 0x95, 0x96, 2805 0x9f, 0x0f, 0xa2, 0x00, 2806 0x02, 0x28, 0x29, 0xb1, 2807 0x08, 0x20, 0x80, 0x00, 2808 0x00, 0x00, 0x00, 0xff, 2809 0xff 2810 }; 2811 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 2812 1, CONTROL_FLAG_NONE, true, &headers)); 2813 if (IsSpdy2()) { 2814 CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData)); 2815 } else if (IsSpdy3()) { 2816 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2817 } else { 2818 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2819 } 2820 } 2821} 2822#endif // !defined(USE_SYSTEM_ZLIB) 2823 2824TEST_P(SpdyFramerTest, CreateWindowUpdate) { 2825 SpdyFramer framer(spdy_version_); 2826 2827 { 2828 const char kDescription[] = "WINDOW_UPDATE frame"; 2829 const unsigned char kV3FrameData[] = { // Also applies for V2. 2830 0x80, spdy_version_ch_, 0x00, 0x09, 2831 0x00, 0x00, 0x00, 0x08, 2832 0x00, 0x00, 0x00, 0x01, 2833 0x00, 0x00, 0x00, 0x01, 2834 }; 2835 const unsigned char kV4FrameData[] = { 2836 0x00, 0x0c, 0x09, 0x00, 2837 0x00, 0x00, 0x00, 0x01, 2838 0x00, 0x00, 0x00, 0x01, 2839 }; 2840 scoped_ptr<SpdyFrame> frame( 2841 framer.CreateWindowUpdate(1, 1)); 2842 if (IsSpdy4()) { 2843 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2844 } else { 2845 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2846 } 2847 } 2848 2849 { 2850 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID"; 2851 const unsigned char kV3FrameData[] = { // Also applies for V2. 2852 0x80, spdy_version_ch_, 0x00, 0x09, 2853 0x00, 0x00, 0x00, 0x08, 2854 0x7f, 0xff, 0xff, 0xff, 2855 0x00, 0x00, 0x00, 0x01, 2856 }; 2857 const unsigned char kV4FrameData[] = { 2858 0x00, 0x0c, 0x09, 0x00, 2859 0x7f, 0xff, 0xff, 0xff, 2860 0x00, 0x00, 0x00, 0x01, 2861 }; 2862 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(0x7FFFFFFF, 1)); 2863 if (IsSpdy4()) { 2864 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2865 } else { 2866 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2867 } 2868 } 2869 2870 { 2871 const char kDescription[] = "WINDOW_UPDATE frame with max window delta"; 2872 const unsigned char kV3FrameData[] = { // Also applies for V2. 2873 0x80, spdy_version_ch_, 0x00, 0x09, 2874 0x00, 0x00, 0x00, 0x08, 2875 0x00, 0x00, 0x00, 0x01, 2876 0x7f, 0xff, 0xff, 0xff, 2877 }; 2878 const unsigned char kV4FrameData[] = { 2879 0x00, 0x0c, 0x09, 0x00, 2880 0x00, 0x00, 0x00, 0x01, 2881 0x7f, 0xff, 0xff, 0xff, 2882 }; 2883 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x7FFFFFFF)); 2884 if (IsSpdy4()) { 2885 CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData)); 2886 } else { 2887 CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData)); 2888 } 2889 } 2890} 2891 2892TEST_P(SpdyFramerTest, SerializeBlocked) { 2893 if (spdy_version_ < SPDY4) { 2894 return; 2895 } 2896 2897 SpdyFramer framer(spdy_version_); 2898 2899 const char kDescription[] = "BLOCKED frame"; 2900 const unsigned char kFrameData[] = { 2901 0x00, 0x08, 0x0b, 0x00, 2902 0x00, 0x00, 0x00, 0x00, 2903 }; 2904 SpdyBlockedIR blocked_ir(0); 2905 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeBlocked(blocked_ir)); 2906 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 2907 2908} 2909 2910TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) { 2911 SpdyHeaderBlock headers; 2912 headers["aa"] = "vv"; 2913 headers["bb"] = "ww"; 2914 SpdyFramer framer(spdy_version_); 2915 scoped_ptr<SpdyFrame> control_frame( 2916 framer.CreateSynStream(1, // stream_id 2917 0, // associated_stream_id 2918 1, // priority 2919 0, // credential_slot 2920 CONTROL_FLAG_NONE, 2921 true, // compress 2922 &headers)); 2923 EXPECT_TRUE(control_frame.get() != NULL); 2924 TestSpdyVisitor visitor(spdy_version_); 2925 visitor.use_compression_ = true; 2926 visitor.SimulateInFramer( 2927 reinterpret_cast<unsigned char*>(control_frame->data()), 2928 control_frame->size()); 2929 EXPECT_EQ(1, visitor.syn_frame_count_); 2930 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_)); 2931} 2932 2933TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) { 2934 SpdyHeaderBlock headers; 2935 headers["alpha"] = "beta"; 2936 headers["gamma"] = "delta"; 2937 SpdyFramer framer(spdy_version_); 2938 scoped_ptr<SpdyFrame> control_frame( 2939 framer.CreateSynReply(1, // stream_id 2940 CONTROL_FLAG_NONE, 2941 true, // compress 2942 &headers)); 2943 EXPECT_TRUE(control_frame.get() != NULL); 2944 TestSpdyVisitor visitor(spdy_version_); 2945 visitor.use_compression_ = true; 2946 visitor.SimulateInFramer( 2947 reinterpret_cast<unsigned char*>(control_frame->data()), 2948 control_frame->size()); 2949 EXPECT_EQ(1, visitor.syn_reply_frame_count_); 2950 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_)); 2951} 2952 2953TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) { 2954 SpdyHeaderBlock headers; 2955 headers["alpha"] = "beta"; 2956 headers["gamma"] = "delta"; 2957 SpdyFramer framer(spdy_version_); 2958 scoped_ptr<SpdyFrame> control_frame( 2959 framer.CreateHeaders(1, // stream_id 2960 CONTROL_FLAG_NONE, 2961 true, // compress 2962 &headers)); 2963 EXPECT_TRUE(control_frame.get() != NULL); 2964 TestSpdyVisitor visitor(spdy_version_); 2965 visitor.use_compression_ = true; 2966 visitor.SimulateInFramer( 2967 reinterpret_cast<unsigned char*>(control_frame->data()), 2968 control_frame->size()); 2969 EXPECT_EQ(1, visitor.headers_frame_count_); 2970 // control_frame_header_data_count_ depends on the random sequence 2971 // produced by rand(), so adding, removing or running single tests 2972 // alters this value. The best we can do is assert that it happens 2973 // at least twice. 2974 EXPECT_LE(2, visitor.control_frame_header_data_count_); 2975 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); 2976 EXPECT_EQ(0, visitor.zero_length_data_frame_count_); 2977 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_)); 2978} 2979 2980TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) { 2981 SpdyHeaderBlock headers; 2982 headers["alpha"] = "beta"; 2983 headers["gamma"] = "delta"; 2984 SpdyFramer framer(spdy_version_); 2985 scoped_ptr<SpdyFrame> control_frame( 2986 framer.CreateHeaders(1, // stream_id 2987 CONTROL_FLAG_FIN, 2988 true, // compress 2989 &headers)); 2990 EXPECT_TRUE(control_frame.get() != NULL); 2991 TestSpdyVisitor visitor(spdy_version_); 2992 visitor.use_compression_ = true; 2993 visitor.SimulateInFramer( 2994 reinterpret_cast<unsigned char*>(control_frame->data()), 2995 control_frame->size()); 2996 EXPECT_EQ(1, visitor.headers_frame_count_); 2997 // control_frame_header_data_count_ depends on the random sequence 2998 // produced by rand(), so adding, removing or running single tests 2999 // alters this value. The best we can do is assert that it happens 3000 // at least twice. 3001 EXPECT_LE(2, visitor.control_frame_header_data_count_); 3002 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); 3003 EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 3004 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_)); 3005} 3006 3007TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) { 3008 // First find the size of the header value in order to just reach the control 3009 // frame max size. 3010 SpdyFramer framer(spdy_version_); 3011 framer.set_enable_compression(false); 3012 SpdyHeaderBlock headers; 3013 headers["aa"] = ""; 3014 scoped_ptr<SpdyFrame> control_frame( 3015 framer.CreateSynStream(1, // stream_id 3016 0, // associated_stream_id 3017 1, // priority 3018 0, // credential_slot 3019 CONTROL_FLAG_NONE, 3020 false, // compress 3021 &headers)); 3022 const size_t kBigValueSize = 3023 framer.GetControlFrameBufferMaxSize() - control_frame->size(); 3024 3025 // Create a frame at exatly that size. 3026 string big_value(kBigValueSize, 'x'); 3027 headers["aa"] = big_value.c_str(); 3028 control_frame.reset( 3029 framer.CreateSynStream(1, // stream_id 3030 0, // associated_stream_id 3031 1, // priority 3032 0, // credential_slot 3033 CONTROL_FLAG_NONE, 3034 false, // compress 3035 &headers)); 3036 EXPECT_TRUE(control_frame.get() != NULL); 3037 EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size()); 3038 3039 TestSpdyVisitor visitor(spdy_version_); 3040 visitor.SimulateInFramer( 3041 reinterpret_cast<unsigned char*>(control_frame->data()), 3042 control_frame->size()); 3043 EXPECT_TRUE(visitor.header_buffer_valid_); 3044 EXPECT_EQ(0, visitor.error_count_); 3045 EXPECT_EQ(1, visitor.syn_frame_count_); 3046 EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); 3047 EXPECT_EQ(0, visitor.zero_length_data_frame_count_); 3048 EXPECT_LT(kBigValueSize, visitor.header_buffer_length_); 3049} 3050 3051TEST_P(SpdyFramerTest, ControlFrameTooLarge) { 3052 // First find the size of the header value in order to just reach the control 3053 // frame max size. 3054 SpdyFramer framer(spdy_version_); 3055 framer.set_enable_compression(false); 3056 SpdyHeaderBlock headers; 3057 headers["aa"] = ""; 3058 scoped_ptr<SpdyFrame> control_frame( 3059 framer.CreateSynStream(1, // stream_id 3060 0, // associated_stream_id 3061 1, // priority 3062 0, // credential_slot 3063 CONTROL_FLAG_NONE, 3064 false, // compress 3065 &headers)); 3066 const size_t kBigValueSize = 3067 framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1; 3068 3069 // Create a frame at exatly that size. 3070 string big_value(kBigValueSize, 'x'); 3071 headers["aa"] = big_value.c_str(); 3072 control_frame.reset( 3073 framer.CreateSynStream(1, // stream_id 3074 0, // associated_stream_id 3075 1, // priority 3076 0, // credential_slot 3077 CONTROL_FLAG_NONE, 3078 false, // compress 3079 &headers)); 3080 EXPECT_TRUE(control_frame.get() != NULL); 3081 EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1, 3082 control_frame->size()); 3083 3084 TestSpdyVisitor visitor(spdy_version_); 3085 visitor.SimulateInFramer( 3086 reinterpret_cast<unsigned char*>(control_frame->data()), 3087 control_frame->size()); 3088 EXPECT_FALSE(visitor.header_buffer_valid_); 3089 EXPECT_EQ(1, visitor.error_count_); 3090 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE, 3091 visitor.framer_.error_code()); 3092 EXPECT_EQ(0, visitor.syn_frame_count_); 3093 EXPECT_EQ(0u, visitor.header_buffer_length_); 3094} 3095 3096// Check that the framer stops delivering header data chunks once the visitor 3097// declares it doesn't want any more. This is important to guard against 3098// "zip bomb" types of attacks. 3099TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) { 3100 SpdyHeaderBlock headers; 3101 const size_t kHeaderBufferChunks = 4; 3102 const size_t kHeaderBufferSize = 3103 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks; 3104 const size_t kBigValueSize = kHeaderBufferSize * 2; 3105 string big_value(kBigValueSize, 'x'); 3106 headers["aa"] = big_value.c_str(); 3107 SpdyFramer framer(spdy_version_); 3108 scoped_ptr<SpdyFrame> control_frame( 3109 framer.CreateSynStream(1, // stream_id 3110 0, // associated_stream_id 3111 1, // priority 3112 0, // credential_slot 3113 CONTROL_FLAG_FIN, // half close 3114 true, // compress 3115 &headers)); 3116 EXPECT_TRUE(control_frame.get() != NULL); 3117 TestSpdyVisitor visitor(spdy_version_); 3118 visitor.set_header_buffer_size(kHeaderBufferSize); 3119 visitor.use_compression_ = true; 3120 visitor.SimulateInFramer( 3121 reinterpret_cast<unsigned char*>(control_frame->data()), 3122 control_frame->size()); 3123 EXPECT_FALSE(visitor.header_buffer_valid_); 3124 EXPECT_EQ(1, visitor.error_count_); 3125 EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE, 3126 visitor.framer_.error_code()); 3127 3128 // The framer should have stoped delivering chunks after the visitor 3129 // signaled "stop" by returning false from OnControlFrameHeaderData(). 3130 // 3131 // control_frame_header_data_count_ depends on the random sequence 3132 // produced by rand(), so adding, removing or running single tests 3133 // alters this value. The best we can do is assert that it happens 3134 // at least kHeaderBufferChunks + 1. 3135 EXPECT_LE(kHeaderBufferChunks + 1, 3136 static_cast<unsigned>(visitor.control_frame_header_data_count_)); 3137 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_); 3138 3139 // The framer should not have sent half-close to the visitor. 3140 EXPECT_EQ(0, visitor.zero_length_data_frame_count_); 3141} 3142 3143TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) { 3144 SpdyHeaderBlock headers; 3145 headers["aa"] = "alpha beta gamma delta"; 3146 SpdyFramer framer(spdy_version_); 3147 framer.set_enable_compression(false); 3148 // Construct a SYN_STREAM control frame without compressing the header block, 3149 // and have the framer try to decompress it. This will cause the framer to 3150 // deal with a decompression error. 3151 scoped_ptr<SpdyFrame> control_frame( 3152 framer.CreateSynStream(1, // stream_id 3153 0, // associated_stream_id 3154 1, // priority 3155 0, // credential_slot 3156 CONTROL_FLAG_NONE, 3157 false, // compress 3158 &headers)); 3159 TestSpdyVisitor visitor(spdy_version_); 3160 visitor.use_compression_ = true; 3161 visitor.SimulateInFramer( 3162 reinterpret_cast<unsigned char*>(control_frame->data()), 3163 control_frame->size()); 3164 EXPECT_EQ(1, visitor.error_count_); 3165 EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code()); 3166 EXPECT_EQ(0u, visitor.header_buffer_length_); 3167} 3168 3169TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) { 3170 // Create a GoAway frame that has a few extra bytes at the end. 3171 // We create enough overhead to overflow the framer's control frame buffer. 3172 ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize); 3173 const unsigned char length = 1 + SpdyFramer::kControlFrameBufferSize; 3174 const unsigned char kV3FrameData[] = { // Also applies for V2. 3175 0x80, spdy_version_ch_, 0x00, 0x07, 3176 0x00, 0x00, 0x00, length, 3177 0x00, 0x00, 0x00, 0x00, 3178 0x00, 0x00, 0x00, 0x00, 3179 }; 3180 const unsigned char kV4FrameData[] = { 3181 0x00, static_cast<uint8>(length + 4), 0x07, 0x00, 3182 0x00, 0x00, 0x00, 0x00, 3183 0x00, 0x00, 0x00, 0x00, 3184 }; 3185 SpdyFramer framer(spdy_version_); 3186 const size_t pad_length = 3187 length + framer.GetControlFrameHeaderSize() - 3188 (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData)); 3189 string pad('A', pad_length); 3190 TestSpdyVisitor visitor(spdy_version_); 3191 3192 if (IsSpdy4()) { 3193 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData)); 3194 } else { 3195 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData)); 3196 } 3197 visitor.SimulateInFramer( 3198 reinterpret_cast<const unsigned char*>(pad.c_str()), 3199 pad.length()); 3200 3201 EXPECT_EQ(1, visitor.error_count_); // This generated an error. 3202 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, 3203 visitor.framer_.error_code()); 3204 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed. 3205} 3206 3207TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) { 3208 SpdyFramer framer(spdy_version_); 3209 SettingsMap settings; 3210 scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings)); 3211 SetFrameLength(control_frame.get(), 0, spdy_version_); 3212 TestSpdyVisitor visitor(spdy_version_); 3213 visitor.use_compression_ = false; 3214 visitor.SimulateInFramer( 3215 reinterpret_cast<unsigned char*>(control_frame->data()), 3216 framer.GetControlFrameHeaderSize()); 3217 // Should generate an error, since zero-len settings frames are unsupported. 3218 EXPECT_EQ(1, visitor.error_count_); 3219} 3220 3221// Tests handling of SETTINGS frames with invalid length. 3222TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) { 3223 SpdyFramer framer(spdy_version_); 3224 SettingsMap settings; 3225 // Add a setting to pad the frame so that we don't get a buffer overflow when 3226 // calling SimulateInFramer() below. 3227 settings[SETTINGS_UPLOAD_BANDWIDTH] = 3228 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, 0x00000002); 3229 scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings)); 3230 const size_t kNewLength = 5; 3231 SetFrameLength(control_frame.get(), kNewLength, spdy_version_); 3232 TestSpdyVisitor visitor(spdy_version_); 3233 visitor.use_compression_ = false; 3234 visitor.SimulateInFramer( 3235 reinterpret_cast<unsigned char*>(control_frame->data()), 3236 framer.GetControlFrameHeaderSize() + kNewLength); 3237 // Should generate an error, since zero-len settings frames are unsupported. 3238 EXPECT_EQ(1, visitor.error_count_); 3239} 3240 3241// Tests handling of SETTINGS frames larger than the frame buffer size. 3242TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) { 3243 SpdyFramer framer(spdy_version_); 3244 SettingsMap settings; 3245 SpdySettingsFlags flags = SETTINGS_FLAG_PLEASE_PERSIST; 3246 settings[SETTINGS_UPLOAD_BANDWIDTH] = 3247 SettingsFlagsAndValue(flags, 0x00000002); 3248 settings[SETTINGS_DOWNLOAD_BANDWIDTH] = 3249 SettingsFlagsAndValue(flags, 0x00000003); 3250 settings[SETTINGS_ROUND_TRIP_TIME] = SettingsFlagsAndValue(flags, 0x00000004); 3251 scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings)); 3252 EXPECT_LT(SpdyFramer::kControlFrameBufferSize, 3253 control_frame->size()); 3254 TestSpdyVisitor visitor(spdy_version_); 3255 visitor.use_compression_ = false; 3256 3257 // Read all at once. 3258 visitor.SimulateInFramer( 3259 reinterpret_cast<unsigned char*>(control_frame->data()), 3260 control_frame->size()); 3261 EXPECT_EQ(0, visitor.error_count_); 3262 EXPECT_EQ(settings.size(), static_cast<unsigned>(visitor.setting_count_)); 3263 3264 // Read data in small chunks. 3265 size_t framed_data = 0; 3266 size_t unframed_data = control_frame->size(); 3267 size_t kReadChunkSize = 5; // Read five bytes at a time. 3268 while (unframed_data > 0) { 3269 size_t to_read = min(kReadChunkSize, unframed_data); 3270 visitor.SimulateInFramer( 3271 reinterpret_cast<unsigned char*>(control_frame->data() + framed_data), 3272 to_read); 3273 unframed_data -= to_read; 3274 framed_data += to_read; 3275 } 3276 EXPECT_EQ(0, visitor.error_count_); 3277 EXPECT_EQ(settings.size() * 2, static_cast<unsigned>(visitor.setting_count_)); 3278} 3279 3280// Tests handling of SETTINGS frame with duplicate entries. 3281TEST_P(SpdyFramerTest, ReadDuplicateSettings) { 3282 SpdyFramer framer(spdy_version_); 3283 3284 const unsigned char kV2FrameData[] = { 3285 0x80, spdy_version_ch_, 0x00, 0x04, 3286 0x00, 0x00, 0x00, 0x1C, 3287 0x00, 0x00, 0x00, 0x03, 3288 0x01, 0x00, 0x00, 0x00, // 1st Setting 3289 0x00, 0x00, 0x00, 0x02, 3290 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting 3291 0x00, 0x00, 0x00, 0x03, 3292 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting 3293 0x00, 0x00, 0x00, 0x03, 3294 }; 3295 const unsigned char kV3FrameData[] = { 3296 0x80, spdy_version_ch_, 0x00, 0x04, 3297 0x00, 0x00, 0x00, 0x1C, 3298 0x00, 0x00, 0x00, 0x03, 3299 0x00, 0x00, 0x00, 0x01, // 1st Setting 3300 0x00, 0x00, 0x00, 0x02, 3301 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting 3302 0x00, 0x00, 0x00, 0x03, 3303 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting 3304 0x00, 0x00, 0x00, 0x03, 3305 }; 3306 const unsigned char kV4FrameData[] = { 3307 0x00, 0x24, 0x04, 0x00, 3308 0x00, 0x00, 0x00, 0x00, 3309 0x00, 0x00, 0x00, 0x03, 3310 0x00, 0x00, 0x00, 0x01, // 1st Setting 3311 0x00, 0x00, 0x00, 0x02, 3312 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting 3313 0x00, 0x00, 0x00, 0x03, 3314 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting 3315 0x00, 0x00, 0x00, 0x03, 3316 }; 3317 3318 TestSpdyVisitor visitor(spdy_version_); 3319 visitor.use_compression_ = false; 3320 if (IsSpdy2()) { 3321 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData)); 3322 } else if (IsSpdy3()) { 3323 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData)); 3324 } else { 3325 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData)); 3326 } 3327 EXPECT_EQ(1, visitor.error_count_); 3328 EXPECT_EQ(1, visitor.setting_count_); 3329} 3330 3331// Tests handling of SETTINGS frame with entries out of order. 3332TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) { 3333 SpdyFramer framer(spdy_version_); 3334 3335 const unsigned char kV2FrameData[] = { 3336 0x80, spdy_version_ch_, 0x00, 0x04, 3337 0x00, 0x00, 0x00, 0x1C, 3338 0x00, 0x00, 0x00, 0x03, 3339 0x02, 0x00, 0x00, 0x00, // 1st Setting 3340 0x00, 0x00, 0x00, 0x02, 3341 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting 3342 0x00, 0x00, 0x00, 0x03, 3343 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting 3344 0x00, 0x00, 0x00, 0x03, 3345 }; 3346 const unsigned char kV3FrameData[] = { 3347 0x80, spdy_version_ch_, 0x00, 0x04, 3348 0x00, 0x00, 0x00, 0x1C, 3349 0x00, 0x00, 0x00, 0x03, 3350 0x00, 0x00, 0x00, 0x02, // 1st Setting 3351 0x00, 0x00, 0x00, 0x02, 3352 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting 3353 0x00, 0x00, 0x00, 0x03, 3354 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting 3355 0x00, 0x00, 0x00, 0x03, 3356 }; 3357 const unsigned char kV4FrameData[] = { 3358 0x00, 0x24, 0x04, 0x00, 3359 0x00, 0x00, 0x00, 0x00, 3360 0x00, 0x00, 0x00, 0x03, 3361 0x00, 0x00, 0x00, 0x02, // 1st Setting 3362 0x00, 0x00, 0x00, 0x02, 3363 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting 3364 0x00, 0x00, 0x00, 0x03, 3365 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting 3366 0x00, 0x00, 0x00, 0x03, 3367 }; 3368 3369 TestSpdyVisitor visitor(spdy_version_); 3370 visitor.use_compression_ = false; 3371 if (IsSpdy2()) { 3372 visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData)); 3373 } else if (IsSpdy3()) { 3374 visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData)); 3375 } else { 3376 visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData)); 3377 } 3378 EXPECT_EQ(1, visitor.error_count_); 3379 EXPECT_EQ(1, visitor.setting_count_); 3380} 3381 3382TEST_P(SpdyFramerTest, ReadWindowUpdate) { 3383 SpdyFramer framer(spdy_version_); 3384 scoped_ptr<SpdyFrame> control_frame( 3385 framer.CreateWindowUpdate(1, 2)); 3386 TestSpdyVisitor visitor(spdy_version_); 3387 visitor.SimulateInFramer( 3388 reinterpret_cast<unsigned char*>(control_frame->data()), 3389 control_frame->size()); 3390 EXPECT_EQ(1u, visitor.last_window_update_stream_); 3391 EXPECT_EQ(2u, visitor.last_window_update_delta_); 3392} 3393 3394TEST_P(SpdyFramerTest, ReadCredentialFrame) { 3395 SpdyCredential credential; 3396 credential.slot = 3; 3397 credential.proof = "proof"; 3398 credential.certs.push_back("a cert"); 3399 credential.certs.push_back("another cert"); 3400 credential.certs.push_back("final cert"); 3401 SpdyFramer framer(spdy_version_); 3402 scoped_ptr<SpdyFrame> control_frame( 3403 framer.CreateCredentialFrame(credential)); 3404 EXPECT_TRUE(control_frame.get() != NULL); 3405 TestSpdyVisitor visitor(spdy_version_); 3406 visitor.use_compression_ = false; 3407 visitor.SimulateInFramer( 3408 reinterpret_cast<unsigned char*>(control_frame->data()), 3409 control_frame->size()); 3410 EXPECT_EQ(0, visitor.error_count_); 3411 EXPECT_EQ(control_frame->size() - framer.GetControlFrameHeaderSize(), 3412 visitor.credential_buffer_length_); 3413 EXPECT_EQ(credential.slot, visitor.credential_.slot); 3414 EXPECT_EQ(credential.proof, visitor.credential_.proof); 3415 EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size()); 3416 for (size_t i = 0; i < credential.certs.size(); i++) { 3417 EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]); 3418 } 3419} 3420 3421TEST_P(SpdyFramerTest, ReadCredentialFrameOneByteAtATime) { 3422 SpdyCredential credential; 3423 credential.slot = 3; 3424 credential.proof = "proof"; 3425 credential.certs.push_back("a cert"); 3426 credential.certs.push_back("another cert"); 3427 credential.certs.push_back("final cert"); 3428 SpdyFramer framer(spdy_version_); 3429 scoped_ptr<SpdyFrame> control_frame( 3430 framer.CreateCredentialFrame(credential)); 3431 EXPECT_TRUE(control_frame.get() != NULL); 3432 TestSpdyVisitor visitor(spdy_version_); 3433 visitor.use_compression_ = false; 3434 // Read one byte at a time to make sure we handle edge cases 3435 unsigned char* data = 3436 reinterpret_cast<unsigned char*>(control_frame->data()); 3437 for (size_t idx = 0; idx < control_frame->size(); ++idx) { 3438 visitor.SimulateInFramer(data + idx, 1); 3439 ASSERT_EQ(0, visitor.error_count_); 3440 } 3441 EXPECT_EQ(0, visitor.error_count_); 3442 EXPECT_EQ(control_frame->size() - framer.GetControlFrameHeaderSize(), 3443 visitor.credential_buffer_length_); 3444 EXPECT_EQ(credential.slot, visitor.credential_.slot); 3445 EXPECT_EQ(credential.proof, visitor.credential_.proof); 3446 EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size()); 3447 for (size_t i = 0; i < credential.certs.size(); i++) { 3448 EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]); 3449 } 3450} 3451 3452TEST_P(SpdyFramerTest, ReadCredentialFrameWithNoPayload) { 3453 SpdyCredential credential; 3454 credential.slot = 3; 3455 credential.proof = "proof"; 3456 credential.certs.push_back("a cert"); 3457 credential.certs.push_back("another cert"); 3458 credential.certs.push_back("final cert"); 3459 SpdyFramer framer(spdy_version_); 3460 scoped_ptr<SpdyFrame> control_frame( 3461 framer.CreateCredentialFrame(credential)); 3462 EXPECT_TRUE(control_frame.get() != NULL); 3463 TestSpdyVisitor visitor(spdy_version_); 3464 visitor.use_compression_ = false; 3465 SetFrameLength(control_frame.get(), 0, spdy_version_); 3466 unsigned char* data = 3467 reinterpret_cast<unsigned char*>(control_frame->data()); 3468 visitor.SimulateInFramer(data, framer.GetControlFrameHeaderSize()); 3469 EXPECT_EQ(1, visitor.error_count_); 3470} 3471 3472TEST_P(SpdyFramerTest, ReadCredentialFrameWithCorruptProof) { 3473 SpdyCredential credential; 3474 credential.slot = 3; 3475 credential.proof = "proof"; 3476 credential.certs.push_back("a cert"); 3477 credential.certs.push_back("another cert"); 3478 credential.certs.push_back("final cert"); 3479 SpdyFramer framer(spdy_version_); 3480 scoped_ptr<SpdyFrame> control_frame( 3481 framer.CreateCredentialFrame(credential)); 3482 EXPECT_TRUE(control_frame.get() != NULL); 3483 TestSpdyVisitor visitor(spdy_version_); 3484 visitor.use_compression_ = false; 3485 unsigned char* data = 3486 reinterpret_cast<unsigned char*>(control_frame->data()); 3487 size_t offset = framer.GetControlFrameHeaderSize() + 4; 3488 data[offset] = 0xFF; // Proof length is past the end of the frame 3489 visitor.SimulateInFramer( 3490 data, control_frame->size()); 3491 EXPECT_EQ(1, visitor.error_count_); 3492} 3493 3494TEST_P(SpdyFramerTest, ReadCredentialFrameWithCorruptCertificate) { 3495 SpdyCredential credential; 3496 credential.slot = 3; 3497 credential.proof = "proof"; 3498 credential.certs.push_back("a cert"); 3499 credential.certs.push_back("another cert"); 3500 credential.certs.push_back("final cert"); 3501 SpdyFramer framer(spdy_version_); 3502 scoped_ptr<SpdyFrame> control_frame( 3503 framer.CreateCredentialFrame(credential)); 3504 EXPECT_TRUE(control_frame.get() != NULL); 3505 TestSpdyVisitor visitor(spdy_version_); 3506 visitor.use_compression_ = false; 3507 unsigned char* data = 3508 reinterpret_cast<unsigned char*>(control_frame->data()); 3509 size_t offset = framer.GetCredentialMinimumSize() + 1; 3510 data[offset] = 0xFF; // Proof length is past the end of the frame 3511 visitor.SimulateInFramer( 3512 data, control_frame->size()); 3513 EXPECT_EQ(1, visitor.error_count_); 3514} 3515 3516TEST_P(SpdyFramerTest, ReadGarbage) { 3517 SpdyFramer framer(spdy_version_); 3518 unsigned char garbage_frame[256]; 3519 memset(garbage_frame, ~0, sizeof(garbage_frame)); 3520 TestSpdyVisitor visitor(spdy_version_); 3521 visitor.use_compression_ = false; 3522 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame)); 3523 EXPECT_EQ(1, visitor.error_count_); 3524} 3525 3526TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) { 3527 if (IsSpdy4()) { 3528 // Not valid for SPDY 4 since there is no version field. 3529 return; 3530 } 3531 SpdyFramer framer(spdy_version_); 3532 const unsigned char kFrameData[] = { 3533 0x80, spdy_version_ch_, 0xff, 0xff, 3534 0xff, 0xff, 0xff, 0xff, 3535 }; 3536 TestSpdyVisitor visitor(spdy_version_); 3537 visitor.use_compression_ = false; 3538 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData)); 3539 EXPECT_EQ(1, visitor.error_count_); 3540} 3541 3542TEST_P(SpdyFramerTest, SizesTest) { 3543 SpdyFramer framer(spdy_version_); 3544 EXPECT_EQ(8u, framer.GetDataFrameMinimumSize()); 3545 if (IsSpdy4()) { 3546 EXPECT_EQ(8u, framer.GetSynReplyMinimumSize()); 3547 EXPECT_EQ(12u, framer.GetRstStreamSize()); 3548 EXPECT_EQ(12u, framer.GetSettingsMinimumSize()); 3549 EXPECT_EQ(12u, framer.GetPingSize()); 3550 EXPECT_EQ(16u, framer.GetGoAwaySize()); 3551 EXPECT_EQ(8u, framer.GetHeadersMinimumSize()); 3552 EXPECT_EQ(12u, framer.GetWindowUpdateSize()); 3553 EXPECT_EQ(10u, framer.GetCredentialMinimumSize()); 3554 EXPECT_EQ(8u, framer.GetBlockedSize()); 3555 EXPECT_EQ(8u, framer.GetFrameMinimumSize()); 3556 EXPECT_EQ(65535u, framer.GetFrameMaximumSize()); 3557 EXPECT_EQ(65527u, framer.GetDataFrameMaximumPayload()); 3558 } else { 3559 EXPECT_EQ(8u, framer.GetControlFrameHeaderSize()); 3560 EXPECT_EQ(18u, framer.GetSynStreamMinimumSize()); 3561 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize()); 3562 EXPECT_EQ(16u, framer.GetRstStreamSize()); 3563 EXPECT_EQ(12u, framer.GetSettingsMinimumSize()); 3564 EXPECT_EQ(12u, framer.GetPingSize()); 3565 EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwaySize()); 3566 EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize()); 3567 EXPECT_EQ(16u, framer.GetWindowUpdateSize()); 3568 EXPECT_EQ(10u, framer.GetCredentialMinimumSize()); 3569 EXPECT_EQ(8u, framer.GetFrameMinimumSize()); 3570 EXPECT_EQ(16777215u, framer.GetFrameMaximumSize()); 3571 EXPECT_EQ(16777207u, framer.GetDataFrameMaximumPayload()); 3572 } 3573} 3574 3575TEST_P(SpdyFramerTest, StateToStringTest) { 3576 EXPECT_STREQ("ERROR", 3577 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR)); 3578 EXPECT_STREQ("AUTO_RESET", 3579 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET)); 3580 EXPECT_STREQ("RESET", 3581 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET)); 3582 EXPECT_STREQ("READING_COMMON_HEADER", 3583 SpdyFramer::StateToString( 3584 SpdyFramer::SPDY_READING_COMMON_HEADER)); 3585 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD", 3586 SpdyFramer::StateToString( 3587 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD)); 3588 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD", 3589 SpdyFramer::StateToString( 3590 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD)); 3591 EXPECT_STREQ("FORWARD_STREAM_FRAME", 3592 SpdyFramer::StateToString( 3593 SpdyFramer::SPDY_FORWARD_STREAM_FRAME)); 3594 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK", 3595 SpdyFramer::StateToString( 3596 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK)); 3597 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK", 3598 SpdyFramer::StateToString( 3599 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK)); 3600 EXPECT_STREQ("SPDY_CREDENTIAL_FRAME_PAYLOAD", 3601 SpdyFramer::StateToString( 3602 SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD)); 3603 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD", 3604 SpdyFramer::StateToString( 3605 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD)); 3606 EXPECT_STREQ("UNKNOWN_STATE", 3607 SpdyFramer::StateToString( 3608 SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1)); 3609} 3610 3611TEST_P(SpdyFramerTest, ErrorCodeToStringTest) { 3612 EXPECT_STREQ("NO_ERROR", 3613 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR)); 3614 EXPECT_STREQ("INVALID_CONTROL_FRAME", 3615 SpdyFramer::ErrorCodeToString( 3616 SpdyFramer::SPDY_INVALID_CONTROL_FRAME)); 3617 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE", 3618 SpdyFramer::ErrorCodeToString( 3619 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE)); 3620 EXPECT_STREQ("ZLIB_INIT_FAILURE", 3621 SpdyFramer::ErrorCodeToString( 3622 SpdyFramer::SPDY_ZLIB_INIT_FAILURE)); 3623 EXPECT_STREQ("UNSUPPORTED_VERSION", 3624 SpdyFramer::ErrorCodeToString( 3625 SpdyFramer::SPDY_UNSUPPORTED_VERSION)); 3626 EXPECT_STREQ("DECOMPRESS_FAILURE", 3627 SpdyFramer::ErrorCodeToString( 3628 SpdyFramer::SPDY_DECOMPRESS_FAILURE)); 3629 EXPECT_STREQ("COMPRESS_FAILURE", 3630 SpdyFramer::ErrorCodeToString( 3631 SpdyFramer::SPDY_COMPRESS_FAILURE)); 3632 EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS", 3633 SpdyFramer::ErrorCodeToString( 3634 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS)); 3635 EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS", 3636 SpdyFramer::ErrorCodeToString( 3637 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS)); 3638 EXPECT_STREQ("UNKNOWN_ERROR", 3639 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR)); 3640} 3641 3642TEST_P(SpdyFramerTest, StatusCodeToStringTest) { 3643 EXPECT_STREQ("INVALID", 3644 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID)); 3645 EXPECT_STREQ("PROTOCOL_ERROR", 3646 SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR)); 3647 EXPECT_STREQ("INVALID_STREAM", 3648 SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM)); 3649 EXPECT_STREQ("REFUSED_STREAM", 3650 SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM)); 3651 EXPECT_STREQ("UNSUPPORTED_VERSION", 3652 SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION)); 3653 EXPECT_STREQ("CANCEL", 3654 SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL)); 3655 EXPECT_STREQ("INTERNAL_ERROR", 3656 SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR)); 3657 EXPECT_STREQ("FLOW_CONTROL_ERROR", 3658 SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR)); 3659 EXPECT_STREQ("UNKNOWN_STATUS", 3660 SpdyFramer::StatusCodeToString(RST_STREAM_NUM_STATUS_CODES)); 3661} 3662 3663TEST_P(SpdyFramerTest, FrameTypeToStringTest) { 3664 EXPECT_STREQ("DATA", 3665 SpdyFramer::FrameTypeToString(DATA)); 3666 EXPECT_STREQ("SYN_STREAM", 3667 SpdyFramer::FrameTypeToString(SYN_STREAM)); 3668 EXPECT_STREQ("SYN_REPLY", 3669 SpdyFramer::FrameTypeToString(SYN_REPLY)); 3670 EXPECT_STREQ("RST_STREAM", 3671 SpdyFramer::FrameTypeToString(RST_STREAM)); 3672 EXPECT_STREQ("SETTINGS", 3673 SpdyFramer::FrameTypeToString(SETTINGS)); 3674 EXPECT_STREQ("NOOP", 3675 SpdyFramer::FrameTypeToString(NOOP)); 3676 EXPECT_STREQ("PING", 3677 SpdyFramer::FrameTypeToString(PING)); 3678 EXPECT_STREQ("GOAWAY", 3679 SpdyFramer::FrameTypeToString(GOAWAY)); 3680 EXPECT_STREQ("HEADERS", 3681 SpdyFramer::FrameTypeToString(HEADERS)); 3682 EXPECT_STREQ("WINDOW_UPDATE", 3683 SpdyFramer::FrameTypeToString(WINDOW_UPDATE)); 3684 EXPECT_STREQ("CREDENTIAL", 3685 SpdyFramer::FrameTypeToString(CREDENTIAL)); 3686} 3687 3688TEST_P(SpdyFramerTest, CatchProbableHttpResponse) { 3689 if (IsSpdy4()) { 3690 // TODO(hkhalil): catch probable HTTP response in SPDY 4? 3691 return; 3692 } 3693 { 3694 testing::StrictMock<test::MockVisitor> visitor; 3695 SpdyFramer framer(spdy_version_); 3696 framer.set_visitor(&visitor); 3697 3698 EXPECT_CALL(visitor, OnError(_)); 3699 framer.ProcessInput("HTTP/1.1", 8); 3700 EXPECT_TRUE(framer.probable_http_response()); 3701 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3702 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code()); 3703 } 3704 { 3705 testing::StrictMock<test::MockVisitor> visitor; 3706 SpdyFramer framer(spdy_version_); 3707 framer.set_visitor(&visitor); 3708 3709 EXPECT_CALL(visitor, OnError(_)); 3710 framer.ProcessInput("HTTP/1.0", 8); 3711 EXPECT_TRUE(framer.probable_http_response()); 3712 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3713 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code()); 3714 } 3715} 3716 3717TEST_P(SpdyFramerTest, DataFrameFlags) { 3718 for (int flags = 0; flags < 256; ++flags) { 3719 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3720 3721 testing::StrictMock<test::MockVisitor> visitor; 3722 SpdyFramer framer(spdy_version_); 3723 framer.set_visitor(&visitor); 3724 3725 scoped_ptr<SpdyFrame> frame( 3726 framer.CreateDataFrame(1, "hello", 5, DATA_FLAG_NONE)); 3727 SetFrameFlags(frame.get(), flags, spdy_version_); 3728 3729 if (flags & ~DATA_FLAG_FIN) { 3730 EXPECT_CALL(visitor, OnError(_)); 3731 } else { 3732 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN)); 3733 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false)); 3734 if (flags & DATA_FLAG_FIN) { 3735 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)); 3736 } 3737 } 3738 3739 framer.ProcessInput(frame->data(), frame->size()); 3740 if (flags & ~DATA_FLAG_FIN) { 3741 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3742 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, 3743 framer.error_code()); 3744 } else { 3745 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3746 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3747 } 3748 } 3749} 3750 3751TEST_P(SpdyFramerTest, SynStreamFrameFlags) { 3752 for (int flags = 0; flags < 256; ++flags) { 3753 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3754 3755 testing::StrictMock<test::MockVisitor> visitor; 3756 SpdyFramer framer(spdy_version_); 3757 framer.set_visitor(&visitor); 3758 3759 EXPECT_CALL(visitor, OnSynStreamCompressed(_, _)); 3760 3761 SpdyHeaderBlock headers; 3762 headers["foo"] = "bar"; 3763 scoped_ptr<SpdyFrame> frame( 3764 framer.CreateSynStream(8, 3, 1, 0, CONTROL_FLAG_NONE, true, &headers)); 3765 SetFrameFlags(frame.get(), flags, spdy_version_); 3766 3767 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { 3768 EXPECT_CALL(visitor, OnError(_)); 3769 } else { 3770 EXPECT_CALL(visitor, OnSynStream(8, 3, 1, 0, flags & CONTROL_FLAG_FIN, 3771 flags & CONTROL_FLAG_UNIDIRECTIONAL)); 3772 EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _)) 3773 .WillRepeatedly(testing::Return(true)); 3774 if (flags & DATA_FLAG_FIN) { 3775 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)); 3776 } 3777 } 3778 3779 framer.ProcessInput(frame->data(), frame->size()); 3780 if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { 3781 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3782 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3783 framer.error_code()); 3784 } else { 3785 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3786 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3787 } 3788 } 3789} 3790 3791TEST_P(SpdyFramerTest, SynReplyFrameFlags) { 3792 for (int flags = 0; flags < 256; ++flags) { 3793 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3794 3795 testing::StrictMock<test::MockVisitor> visitor; 3796 SpdyFramer framer(spdy_version_); 3797 framer.set_visitor(&visitor); 3798 3799 SpdyHeaderBlock headers; 3800 headers["foo"] = "bar"; 3801 scoped_ptr<SpdyFrame> frame( 3802 framer.CreateSynReply(37, CONTROL_FLAG_NONE, true, &headers)); 3803 SetFrameFlags(frame.get(), flags, spdy_version_); 3804 3805 if (flags & ~CONTROL_FLAG_FIN) { 3806 EXPECT_CALL(visitor, OnError(_)); 3807 } else { 3808 EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN)); 3809 EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _)) 3810 .WillRepeatedly(testing::Return(true)); 3811 if (flags & DATA_FLAG_FIN) { 3812 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)); 3813 } 3814 } 3815 3816 framer.ProcessInput(frame->data(), frame->size()); 3817 if (flags & ~CONTROL_FLAG_FIN) { 3818 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3819 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3820 framer.error_code()); 3821 } else { 3822 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3823 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3824 } 3825 } 3826} 3827 3828TEST_P(SpdyFramerTest, RstStreamFrameFlags) { 3829 for (int flags = 0; flags < 256; ++flags) { 3830 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3831 3832 testing::StrictMock<test::MockVisitor> visitor; 3833 SpdyFramer framer(spdy_version_); 3834 framer.set_visitor(&visitor); 3835 3836 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(13, RST_STREAM_CANCEL)); 3837 SetFrameFlags(frame.get(), flags, spdy_version_); 3838 3839 if (flags != 0) { 3840 EXPECT_CALL(visitor, OnError(_)); 3841 } else { 3842 EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL)); 3843 } 3844 3845 framer.ProcessInput(frame->data(), frame->size()); 3846 if (flags != 0) { 3847 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3848 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3849 framer.error_code()); 3850 } else { 3851 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3852 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3853 } 3854 } 3855} 3856 3857TEST_P(SpdyFramerTest, SettingsFrameFlags) { 3858 for (int flags = 0; flags < 256; ++flags) { 3859 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3860 3861 testing::StrictMock<test::MockVisitor> visitor; 3862 SpdyFramer framer(spdy_version_); 3863 framer.set_visitor(&visitor); 3864 3865 SettingsMap settings; 3866 settings[SETTINGS_UPLOAD_BANDWIDTH] = 3867 std::make_pair(SETTINGS_FLAG_NONE, 54321); 3868 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings)); 3869 SetFrameFlags(frame.get(), flags, spdy_version_); 3870 3871 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { 3872 EXPECT_CALL(visitor, OnError(_)); 3873 } else { 3874 EXPECT_CALL(visitor, OnSettings( 3875 flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS)); 3876 EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH, 3877 SETTINGS_FLAG_NONE, 54321)); 3878 } 3879 3880 framer.ProcessInput(frame->data(), frame->size()); 3881 if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { 3882 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3883 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3884 framer.error_code()); 3885 } else { 3886 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3887 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3888 } 3889 } 3890} 3891 3892TEST_P(SpdyFramerTest, GoawayFrameFlags) { 3893 for (int flags = 0; flags < 256; ++flags) { 3894 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3895 3896 testing::StrictMock<test::MockVisitor> visitor; 3897 SpdyFramer framer(spdy_version_); 3898 framer.set_visitor(&visitor); 3899 3900 scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(97, GOAWAY_OK)); 3901 SetFrameFlags(frame.get(), flags, spdy_version_); 3902 3903 if (flags != 0) { 3904 EXPECT_CALL(visitor, OnError(_)); 3905 } else { 3906 EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK)); 3907 } 3908 3909 framer.ProcessInput(frame->data(), frame->size()); 3910 if (flags != 0) { 3911 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3912 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3913 framer.error_code()); 3914 } else { 3915 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3916 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3917 } 3918 } 3919} 3920 3921TEST_P(SpdyFramerTest, HeadersFrameFlags) { 3922 for (int flags = 0; flags < 256; ++flags) { 3923 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3924 3925 testing::StrictMock<test::MockVisitor> visitor; 3926 SpdyFramer framer(spdy_version_); 3927 framer.set_visitor(&visitor); 3928 3929 SpdyHeaderBlock headers; 3930 headers["foo"] = "bar"; 3931 scoped_ptr<SpdyFrame> frame( 3932 framer.CreateHeaders(57, CONTROL_FLAG_NONE, true, &headers)); 3933 SetFrameFlags(frame.get(), flags, spdy_version_); 3934 3935 if (flags & ~CONTROL_FLAG_FIN) { 3936 EXPECT_CALL(visitor, OnError(_)); 3937 } else { 3938 EXPECT_CALL(visitor, OnHeaders(57, flags & CONTROL_FLAG_FIN)); 3939 EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _)) 3940 .WillRepeatedly(testing::Return(true)); 3941 if (flags & DATA_FLAG_FIN) { 3942 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)); 3943 } 3944 } 3945 3946 framer.ProcessInput(frame->data(), frame->size()); 3947 if (flags & ~CONTROL_FLAG_FIN) { 3948 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3949 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3950 framer.error_code()); 3951 } else { 3952 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3953 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3954 } 3955 } 3956} 3957 3958TEST_P(SpdyFramerTest, PingFrameFlags) { 3959 for (int flags = 0; flags < 256; ++flags) { 3960 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3961 3962 testing::StrictMock<test::MockVisitor> visitor; 3963 SpdyFramer framer(spdy_version_); 3964 framer.set_visitor(&visitor); 3965 3966 scoped_ptr<SpdyFrame> frame(framer.CreatePingFrame(42)); 3967 SetFrameFlags(frame.get(), flags, spdy_version_); 3968 3969 if (flags != 0) { 3970 EXPECT_CALL(visitor, OnError(_)); 3971 } else { 3972 EXPECT_CALL(visitor, OnPing(42)); 3973 } 3974 3975 framer.ProcessInput(frame->data(), frame->size()); 3976 if (flags != 0) { 3977 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 3978 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 3979 framer.error_code()); 3980 } else { 3981 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 3982 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 3983 } 3984 } 3985} 3986 3987TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) { 3988 for (int flags = 0; flags < 256; ++flags) { 3989 SCOPED_TRACE(testing::Message() << "Flags " << flags); 3990 3991 testing::StrictMock<test::MockVisitor> visitor; 3992 SpdyFramer framer(spdy_version_); 3993 framer.set_visitor(&visitor); 3994 3995 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(4, 1024)); 3996 SetFrameFlags(frame.get(), flags, spdy_version_); 3997 3998 if (flags != 0) { 3999 EXPECT_CALL(visitor, OnError(_)); 4000 } else { 4001 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024)); 4002 } 4003 4004 framer.ProcessInput(frame->data(), frame->size()); 4005 if (flags != 0) { 4006 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 4007 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 4008 framer.error_code()); 4009 } else { 4010 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4011 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4012 } 4013 } 4014} 4015 4016TEST_P(SpdyFramerTest, CredentialFrameFlags) { 4017 for (int flags = 0; flags < 256; ++flags) { 4018 SCOPED_TRACE(testing::Message() << "Flags " << flags); 4019 4020 testing::StrictMock<test::MockVisitor> visitor; 4021 SpdyFramer framer(spdy_version_); 4022 framer.set_visitor(&visitor); 4023 4024 SpdyCredential credential; 4025 scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential)); 4026 SetFrameFlags(frame.get(), flags, spdy_version_); 4027 4028 if (flags != 0) { 4029 EXPECT_CALL(visitor, OnError(_)); 4030 } else { 4031 EXPECT_CALL(visitor, OnCredentialFrameData(_, _)) 4032 .WillRepeatedly(testing::Return(true)); 4033 } 4034 4035 framer.ProcessInput(frame->data(), frame->size()); 4036 if (flags != 0) { 4037 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); 4038 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, 4039 framer.error_code()); 4040 } else { 4041 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4042 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4043 } 4044 } 4045} 4046 4047TEST_P(SpdyFramerTest, EmptySynStream) { 4048 SpdyHeaderBlock headers; 4049 4050 testing::StrictMock<test::MockVisitor> visitor; 4051 SpdyFramer framer(spdy_version_); 4052 framer.set_visitor(&visitor); 4053 4054 EXPECT_CALL(visitor, OnSynStreamCompressed(_, _)); 4055 scoped_ptr<SpdyFrame> 4056 frame(framer.CreateSynStream(1, 0, 1, 0, CONTROL_FLAG_NONE, true, 4057 &headers)); 4058 // Adjust size to remove the name/value block. 4059 if (IsSpdy4()) { 4060 SetFrameLength( 4061 frame.get(), 4062 framer.GetSynStreamMinimumSize(), 4063 spdy_version_); 4064 } else { 4065 SetFrameLength( 4066 frame.get(), 4067 framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(), 4068 spdy_version_); 4069 } 4070 4071 EXPECT_CALL(visitor, OnSynStream(1, 0, 1, 0, false, false)); 4072 EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0)); 4073 4074 framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize()); 4075 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4076 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4077} 4078 4079TEST_P(SpdyFramerTest, SettingsFlagsAndId) { 4080 const uint32 kId = 0x020304; 4081 const uint32 kFlags = 0x01; 4082 const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304); 4083 4084 SettingsFlagsAndId id_and_flags = 4085 SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat); 4086 EXPECT_EQ(kId, id_and_flags.id()); 4087 EXPECT_EQ(kFlags, id_and_flags.flags()); 4088 EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_)); 4089} 4090 4091// Test handling of a RST_STREAM with out-of-bounds status codes. 4092TEST_P(SpdyFramerTest, RstStreamStatusBounds) { 4093 DCHECK_GE(0xff, RST_STREAM_NUM_STATUS_CODES); 4094 4095 const unsigned char kV3RstStreamInvalid[] = { 4096 0x80, spdy_version_ch_, 0x00, 0x03, 4097 0x00, 0x00, 0x00, 0x08, 4098 0x00, 0x00, 0x00, 0x01, 4099 0x00, 0x00, 0x00, RST_STREAM_INVALID 4100 }; 4101 const unsigned char kV4RstStreamInvalid[] = { 4102 0x00, 0x0c, 0x03, 0x00, 4103 0x00, 0x00, 0x00, 0x01, 4104 0x00, 0x00, 0x00, RST_STREAM_INVALID 4105 }; 4106 4107 const unsigned char kV3RstStreamNumStatusCodes[] = { 4108 0x80, spdy_version_ch_, 0x00, 0x03, 4109 0x00, 0x00, 0x00, 0x08, 4110 0x00, 0x00, 0x00, 0x01, 4111 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES 4112 }; 4113 const unsigned char kV4RstStreamNumStatusCodes[] = { 4114 0x00, 0x0c, 0x03, 0x00, 4115 0x00, 0x00, 0x00, 0x01, 4116 0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES 4117 }; 4118 4119 testing::StrictMock<test::MockVisitor> visitor; 4120 SpdyFramer framer(spdy_version_); 4121 framer.set_visitor(&visitor); 4122 4123 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID)); 4124 if (IsSpdy4()) { 4125 framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid), 4126 arraysize(kV4RstStreamInvalid)); 4127 } else { 4128 framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid), 4129 arraysize(kV3RstStreamInvalid)); 4130 } 4131 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4132 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4133 4134 EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID)); 4135 if (IsSpdy4()) { 4136 framer.ProcessInput( 4137 reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes), 4138 arraysize(kV4RstStreamNumStatusCodes)); 4139 } else { 4140 framer.ProcessInput( 4141 reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes), 4142 arraysize(kV3RstStreamNumStatusCodes)); 4143 } 4144 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4145 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4146} 4147 4148// Tests handling of a GOAWAY frame with out-of-bounds stream ID. 4149TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) { 4150 const unsigned char kV2FrameData[] = { 4151 0x80, spdy_version_ch_, 0x00, 0x07, 4152 0x00, 0x00, 0x00, 0x04, 4153 0xff, 0xff, 0xff, 0xff, 4154 }; 4155 const unsigned char kV3FrameData[] = { 4156 0x80, spdy_version_ch_, 0x00, 0x07, 4157 0x00, 0x00, 0x00, 0x08, 4158 0xff, 0xff, 0xff, 0xff, 4159 0x00, 0x00, 0x00, 0x00, 4160 }; 4161 const unsigned char kV4FrameData[] = { 4162 0x00, 0x10, 0x07, 0x00, 4163 0x00, 0x00, 0x00, 0x00, 4164 0xff, 0xff, 0xff, 0xff, 4165 0x00, 0x00, 0x00, 0x00, 4166 }; 4167 4168 testing::StrictMock<test::MockVisitor> visitor; 4169 SpdyFramer framer(spdy_version_); 4170 framer.set_visitor(&visitor); 4171 4172 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK)); 4173 if (IsSpdy2()) { 4174 framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData), 4175 arraysize(kV2FrameData)); 4176 } else if (IsSpdy3()) { 4177 framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData), 4178 arraysize(kV3FrameData)); 4179 } else { 4180 framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData), 4181 arraysize(kV4FrameData)); 4182 } 4183 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4184 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4185} 4186 4187TEST_P(SpdyFramerTest, OnBlocked) { 4188 if (spdy_version_ < SPDY4) { 4189 return; 4190 } 4191 4192 const SpdyStreamId kStreamId = 0; 4193 4194 testing::StrictMock<test::MockVisitor> visitor; 4195 SpdyFramer framer(spdy_version_); 4196 framer.set_visitor(&visitor); 4197 4198 EXPECT_CALL(visitor, OnBlocked(kStreamId)); 4199 4200 SpdyBlockedIR blocked_ir(0); 4201 scoped_ptr<SpdySerializedFrame> frame(framer.SerializeBlocked(blocked_ir)); 4202 framer.ProcessInput(frame->data(), framer.GetBlockedSize()); 4203 4204 EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state()); 4205 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()); 4206} 4207 4208} // namespace net 4209