Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 4526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4537 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha"); | 4537 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha"); |
| 4538 std::string alpha_val = | 4538 std::string alpha_val = |
| 4539 (it == response_headers.end()) ? std::string() : it->second; | 4539 (it == response_headers.end()) ? std::string() : it->second; |
| 4540 EXPECT_EQ("beta", alpha_val); | 4540 EXPECT_EQ("beta", alpha_val); |
| 4541 | 4541 |
| 4542 GURL request_url = | 4542 GURL request_url = |
| 4543 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true); | 4543 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true); |
| 4544 EXPECT_EQ(kStreamUrl, request_url); | 4544 EXPECT_EQ(kStreamUrl, request_url); |
| 4545 } | 4545 } |
| 4546 | 4546 |
| 4547 // Regression. Sorta. Push streams and client streams were sharing a single | |
| 4548 // limit for a long time. | |
| 4549 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) { | |
| 4550 SettingsMap new_settings; | |
| 4551 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = | |
| 4552 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2); | |
| 4553 scoped_ptr<SpdyFrame> settings_frame( | |
| 4554 spdy_util_.ConstructSpdySettings(new_settings)); | |
| 4555 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush( | |
| 4556 NULL, 0, 2, 1, "http://www.google.com/a.dat")); | |
| 4557 MockRead reads[] = { | |
| 4558 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3), | |
| 4559 MockRead(ASYNC, 0, 4), | |
| 4560 }; | |
| 4561 | |
| 4562 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck()); | |
| 4563 scoped_ptr<SpdyFrame> req( | |
| 4564 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 4565 MockWrite writes[] = { | |
| 4566 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2), | |
| 4567 }; | |
| 4568 | |
| 4569 DeterministicSocketData data( | |
| 4570 reads, arraysize(reads), writes, arraysize(writes)); | |
| 4571 MockConnect connect_data(SYNCHRONOUS, OK); | |
| 4572 data.set_connect_data(connect_data); | |
| 4573 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | |
| 4574 | |
| 4575 CreateDeterministicNetworkSession(); | |
| 4576 | |
| 4577 base::WeakPtr<SpdySession> session = | |
| 4578 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); | |
| 4579 | |
| 4580 // Read the settings frame. | |
| 4581 data.RunFor(1); | |
| 4582 | |
| 4583 GURL url1(kDefaultURL); | |
| 4584 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously( | |
| 4585 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog()); | |
| 4586 ASSERT_TRUE(spdy_stream1.get() != NULL); | |
| 4587 EXPECT_EQ(0u, spdy_stream1->stream_id()); | |
| 4588 test::StreamDelegateDoNothing delegate1(spdy_stream1); | |
| 4589 spdy_stream1->SetDelegate(&delegate1); | |
| 4590 | |
| 4591 EXPECT_EQ(0u, session->num_active_streams()); | |
| 4592 EXPECT_EQ(1u, session->num_created_streams()); | |
| 4593 EXPECT_EQ(0u, session->num_pushed_streams()); | |
| 4594 EXPECT_EQ(0u, session->num_active_pushed_streams()); | |
| 4595 | |
| 4596 scoped_ptr<SpdyHeaderBlock> headers( | |
| 4597 spdy_util_.ConstructGetHeaderBlock(url1.spec())); | |
| 4598 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); | |
| 4599 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); | |
| 4600 | |
| 4601 // Run until 1st stream is activated. | |
| 4602 EXPECT_EQ(0u, delegate1.stream_id()); | |
| 4603 data.RunFor(2); | |
| 4604 EXPECT_EQ(1u, delegate1.stream_id()); | |
| 4605 EXPECT_EQ(1u, session->num_active_streams()); | |
| 4606 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4607 EXPECT_EQ(0u, session->num_pushed_streams()); | |
| 4608 EXPECT_EQ(0u, session->num_active_pushed_streams()); | |
| 4609 | |
| 4610 // Run until pushed stream is created. | |
| 4611 data.RunFor(1); | |
| 4612 EXPECT_EQ(2u, session->num_active_streams()); | |
| 4613 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4614 EXPECT_EQ(1u, session->num_pushed_streams()); | |
| 4615 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4616 | |
| 4617 // Second stream should not be stalled, although we have 2 active streams, but | |
| 4618 // one of them is push stream and should not be taken into account when we | |
| 4619 // create streams on the client. | |
|
Johnny
2014/07/07 19:58:50
Nice!
| |
| 4620 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously( | |
| 4621 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog()); | |
| 4622 EXPECT_TRUE(spdy_stream2.get() != NULL); | |
| 4623 EXPECT_EQ(2u, session->num_active_streams()); | |
| 4624 EXPECT_EQ(1u, session->num_created_streams()); | |
| 4625 EXPECT_EQ(1u, session->num_pushed_streams()); | |
| 4626 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4627 | |
| 4628 // Read EOF. | |
| 4629 data.RunFor(1); | |
| 4630 } | |
| 4631 | |
| 4632 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) { | |
| 4633 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush( | |
| 4634 NULL, 0, 2, 1, "http://www.google.com/a.dat")); | |
| 4635 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush( | |
| 4636 NULL, 0, 4, 1, "http://www.google.com/b.dat")); | |
| 4637 MockRead reads[] = { | |
| 4638 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2), | |
| 4639 MockRead(ASYNC, 0, 4), | |
| 4640 }; | |
| 4641 | |
| 4642 scoped_ptr<SpdyFrame> req( | |
| 4643 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 4644 scoped_ptr<SpdyFrame> rst( | |
| 4645 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM)); | |
| 4646 MockWrite writes[] = { | |
| 4647 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3), | |
| 4648 }; | |
| 4649 | |
| 4650 DeterministicSocketData data( | |
| 4651 reads, arraysize(reads), writes, arraysize(writes)); | |
| 4652 MockConnect connect_data(SYNCHRONOUS, OK); | |
| 4653 data.set_connect_data(connect_data); | |
| 4654 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | |
| 4655 | |
| 4656 CreateDeterministicNetworkSession(); | |
| 4657 | |
| 4658 base::WeakPtr<SpdySession> session = | |
| 4659 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); | |
| 4660 session->set_max_concurrent_pushed_streams(1); | |
| 4661 | |
| 4662 GURL url1(kDefaultURL); | |
| 4663 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously( | |
| 4664 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog()); | |
| 4665 ASSERT_TRUE(spdy_stream1.get() != NULL); | |
| 4666 EXPECT_EQ(0u, spdy_stream1->stream_id()); | |
| 4667 test::StreamDelegateDoNothing delegate1(spdy_stream1); | |
| 4668 spdy_stream1->SetDelegate(&delegate1); | |
| 4669 | |
| 4670 EXPECT_EQ(0u, session->num_active_streams()); | |
| 4671 EXPECT_EQ(1u, session->num_created_streams()); | |
| 4672 EXPECT_EQ(0u, session->num_pushed_streams()); | |
| 4673 EXPECT_EQ(0u, session->num_active_pushed_streams()); | |
| 4674 | |
| 4675 scoped_ptr<SpdyHeaderBlock> headers( | |
| 4676 spdy_util_.ConstructGetHeaderBlock(url1.spec())); | |
| 4677 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); | |
| 4678 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); | |
| 4679 | |
| 4680 // Run until 1st stream is activated. | |
| 4681 EXPECT_EQ(0u, delegate1.stream_id()); | |
| 4682 data.RunFor(1); | |
| 4683 EXPECT_EQ(1u, delegate1.stream_id()); | |
| 4684 EXPECT_EQ(1u, session->num_active_streams()); | |
| 4685 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4686 EXPECT_EQ(0u, session->num_pushed_streams()); | |
| 4687 EXPECT_EQ(0u, session->num_active_pushed_streams()); | |
| 4688 | |
| 4689 // Run until pushed stream is created. | |
| 4690 data.RunFor(1); | |
| 4691 EXPECT_EQ(2u, session->num_active_streams()); | |
| 4692 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4693 EXPECT_EQ(1u, session->num_pushed_streams()); | |
| 4694 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4695 | |
| 4696 // Reset incoming pushed stream. | |
| 4697 data.RunFor(2); | |
| 4698 EXPECT_EQ(2u, session->num_active_streams()); | |
| 4699 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4700 EXPECT_EQ(1u, session->num_pushed_streams()); | |
| 4701 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4702 | |
| 4703 // Read EOF. | |
| 4704 data.RunFor(1); | |
| 4705 } | |
| 4706 | |
| 4707 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) { | |
| 4708 // Streams in reserved remote state exist only in SPDY4. | |
| 4709 if (spdy_util_.spdy_version() < SPDY4) | |
| 4710 return; | |
| 4711 | |
| 4712 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush( | |
| 4713 NULL, 0, 2, 1, "http://www.google.com/a.dat")); | |
| 4714 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock); | |
| 4715 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat", | |
| 4716 push_headers.get()); | |
| 4717 scoped_ptr<SpdyFrame> push_b( | |
| 4718 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1)); | |
| 4719 scoped_ptr<SpdyFrame> headers_b( | |
| 4720 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0)); | |
| 4721 MockRead reads[] = { | |
| 4722 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2), | |
| 4723 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5), | |
| 4724 }; | |
| 4725 | |
| 4726 scoped_ptr<SpdyFrame> req( | |
| 4727 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 4728 scoped_ptr<SpdyFrame> rst( | |
| 4729 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM)); | |
| 4730 MockWrite writes[] = { | |
| 4731 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4), | |
| 4732 }; | |
| 4733 | |
| 4734 DeterministicSocketData data( | |
| 4735 reads, arraysize(reads), writes, arraysize(writes)); | |
| 4736 MockConnect connect_data(SYNCHRONOUS, OK); | |
| 4737 data.set_connect_data(connect_data); | |
| 4738 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | |
| 4739 | |
| 4740 CreateDeterministicNetworkSession(); | |
| 4741 | |
| 4742 base::WeakPtr<SpdySession> session = | |
| 4743 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); | |
| 4744 session->set_max_concurrent_pushed_streams(1); | |
| 4745 | |
| 4746 GURL url1(kDefaultURL); | |
| 4747 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously( | |
| 4748 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog()); | |
| 4749 ASSERT_TRUE(spdy_stream1.get() != NULL); | |
| 4750 EXPECT_EQ(0u, spdy_stream1->stream_id()); | |
| 4751 test::StreamDelegateDoNothing delegate1(spdy_stream1); | |
| 4752 spdy_stream1->SetDelegate(&delegate1); | |
| 4753 | |
| 4754 EXPECT_EQ(0u, session->num_active_streams()); | |
| 4755 EXPECT_EQ(1u, session->num_created_streams()); | |
| 4756 EXPECT_EQ(0u, session->num_pushed_streams()); | |
| 4757 EXPECT_EQ(0u, session->num_active_pushed_streams()); | |
| 4758 | |
| 4759 scoped_ptr<SpdyHeaderBlock> headers( | |
| 4760 spdy_util_.ConstructGetHeaderBlock(url1.spec())); | |
| 4761 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); | |
| 4762 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); | |
| 4763 | |
| 4764 // Run until 1st stream is activated. | |
| 4765 EXPECT_EQ(0u, delegate1.stream_id()); | |
| 4766 data.RunFor(1); | |
| 4767 EXPECT_EQ(1u, delegate1.stream_id()); | |
| 4768 EXPECT_EQ(1u, session->num_active_streams()); | |
| 4769 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4770 EXPECT_EQ(0u, session->num_pushed_streams()); | |
| 4771 EXPECT_EQ(0u, session->num_active_pushed_streams()); | |
| 4772 | |
| 4773 // Run until pushed stream is created. | |
| 4774 data.RunFor(1); | |
| 4775 EXPECT_EQ(2u, session->num_active_streams()); | |
| 4776 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4777 EXPECT_EQ(1u, session->num_pushed_streams()); | |
| 4778 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4779 | |
| 4780 // Accept promised stream. It should not count towards pushed stream limit. | |
| 4781 data.RunFor(1); | |
| 4782 EXPECT_EQ(3u, session->num_active_streams()); | |
| 4783 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4784 EXPECT_EQ(2u, session->num_pushed_streams()); | |
| 4785 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4786 | |
| 4787 // Reset last pushed stream upon headers reception as it is going to be 2nd, | |
| 4788 // while we accept only one. | |
| 4789 data.RunFor(2); | |
| 4790 EXPECT_EQ(2u, session->num_active_streams()); | |
| 4791 EXPECT_EQ(0u, session->num_created_streams()); | |
| 4792 EXPECT_EQ(1u, session->num_pushed_streams()); | |
| 4793 EXPECT_EQ(1u, session->num_active_pushed_streams()); | |
| 4794 | |
| 4795 // Read EOF. | |
| 4796 data.RunFor(1); | |
| 4797 } | |
| 4798 | |
| 4547 TEST(MapFramerErrorToProtocolError, MapsValues) { | 4799 TEST(MapFramerErrorToProtocolError, MapsValues) { |
| 4548 CHECK_EQ( | 4800 CHECK_EQ( |
| 4549 SPDY_ERROR_INVALID_CONTROL_FRAME, | 4801 SPDY_ERROR_INVALID_CONTROL_FRAME, |
| 4550 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME)); | 4802 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME)); |
| 4551 CHECK_EQ( | 4803 CHECK_EQ( |
| 4552 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS, | 4804 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS, |
| 4553 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS)); | 4805 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS)); |
| 4554 CHECK_EQ( | 4806 CHECK_EQ( |
| 4555 SPDY_ERROR_GOAWAY_FRAME_CORRUPT, | 4807 SPDY_ERROR_GOAWAY_FRAME_CORRUPT, |
| 4556 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT)); | 4808 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT)); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 4587 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, | 4839 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, |
| 4588 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR)); | 4840 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR)); |
| 4589 CHECK_EQ(GOAWAY_COMPRESSION_ERROR, | 4841 CHECK_EQ(GOAWAY_COMPRESSION_ERROR, |
| 4590 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR)); | 4842 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR)); |
| 4591 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR, | 4843 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR, |
| 4592 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR)); | 4844 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR)); |
| 4593 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED)); | 4845 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED)); |
| 4594 } | 4846 } |
| 4595 | 4847 |
| 4596 } // namespace net | 4848 } // namespace net |
| OLD | NEW |