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