Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: net/spdy/spdy_session_unittest.cc

Issue 371273003: Reland "Separate client and server pushed streams limits." (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix active push stream count Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_session.cc ('k') | net/spdy/spdy_stream_test_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 4591 matching lines...) Expand 10 before | Expand all | Expand 10 after
4602 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha"); 4602 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4603 std::string alpha_val = 4603 std::string alpha_val =
4604 (it == response_headers.end()) ? std::string() : it->second; 4604 (it == response_headers.end()) ? std::string() : it->second;
4605 EXPECT_EQ("beta", alpha_val); 4605 EXPECT_EQ("beta", alpha_val);
4606 4606
4607 GURL request_url = 4607 GURL request_url =
4608 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true); 4608 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4609 EXPECT_EQ(kStreamUrl, request_url); 4609 EXPECT_EQ(kStreamUrl, request_url);
4610 } 4610 }
4611 4611
4612 // Regression. Sorta. Push streams and client streams were sharing a single
4613 // limit for a long time.
4614 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4615 SettingsMap new_settings;
4616 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4617 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4618 scoped_ptr<SpdyFrame> settings_frame(
4619 spdy_util_.ConstructSpdySettings(new_settings));
4620 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4621 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4622 MockRead reads[] = {
4623 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4624 MockRead(ASYNC, 0, 4),
4625 };
4626
4627 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4628 scoped_ptr<SpdyFrame> req(
4629 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4630 MockWrite writes[] = {
4631 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4632 };
4633
4634 DeterministicSocketData data(
4635 reads, arraysize(reads), writes, arraysize(writes));
4636 MockConnect connect_data(SYNCHRONOUS, OK);
4637 data.set_connect_data(connect_data);
4638 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4639
4640 CreateDeterministicNetworkSession();
4641
4642 base::WeakPtr<SpdySession> session =
4643 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4644
4645 // Read the settings frame.
4646 data.RunFor(1);
4647
4648 GURL url1(kDefaultURL);
4649 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4650 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4651 ASSERT_TRUE(spdy_stream1.get() != NULL);
4652 EXPECT_EQ(0u, spdy_stream1->stream_id());
4653 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4654 spdy_stream1->SetDelegate(&delegate1);
4655
4656 EXPECT_EQ(0u, session->num_active_streams());
4657 EXPECT_EQ(1u, session->num_created_streams());
4658 EXPECT_EQ(0u, session->num_pushed_streams());
4659 EXPECT_EQ(0u, session->num_active_pushed_streams());
4660
4661 scoped_ptr<SpdyHeaderBlock> headers(
4662 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4663 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4664 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4665
4666 // Run until 1st stream is activated.
4667 EXPECT_EQ(0u, delegate1.stream_id());
4668 data.RunFor(2);
4669 EXPECT_EQ(1u, delegate1.stream_id());
4670 EXPECT_EQ(1u, session->num_active_streams());
4671 EXPECT_EQ(0u, session->num_created_streams());
4672 EXPECT_EQ(0u, session->num_pushed_streams());
4673 EXPECT_EQ(0u, session->num_active_pushed_streams());
4674
4675 // Run until pushed stream is created.
4676 data.RunFor(1);
4677 EXPECT_EQ(2u, session->num_active_streams());
4678 EXPECT_EQ(0u, session->num_created_streams());
4679 EXPECT_EQ(1u, session->num_pushed_streams());
4680 EXPECT_EQ(1u, session->num_active_pushed_streams());
4681
4682 // Second stream should not be stalled, although we have 2 active streams, but
4683 // one of them is push stream and should not be taken into account when we
4684 // create streams on the client.
4685 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4686 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4687 EXPECT_TRUE(spdy_stream2.get() != NULL);
4688 EXPECT_EQ(2u, session->num_active_streams());
4689 EXPECT_EQ(1u, session->num_created_streams());
4690 EXPECT_EQ(1u, session->num_pushed_streams());
4691 EXPECT_EQ(1u, session->num_active_pushed_streams());
4692
4693 // Read EOF.
4694 data.RunFor(1);
4695 }
4696
4697 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4698 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4699 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4700 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4701 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4702 MockRead reads[] = {
4703 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4704 MockRead(ASYNC, 0, 4),
4705 };
4706
4707 scoped_ptr<SpdyFrame> req(
4708 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4709 scoped_ptr<SpdyFrame> rst(
4710 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4711 MockWrite writes[] = {
4712 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4713 };
4714
4715 DeterministicSocketData data(
4716 reads, arraysize(reads), writes, arraysize(writes));
4717 MockConnect connect_data(SYNCHRONOUS, OK);
4718 data.set_connect_data(connect_data);
4719 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4720
4721 CreateDeterministicNetworkSession();
4722
4723 base::WeakPtr<SpdySession> session =
4724 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4725 session->set_max_concurrent_pushed_streams(1);
4726
4727 GURL url1(kDefaultURL);
4728 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4729 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4730 ASSERT_TRUE(spdy_stream1.get() != NULL);
4731 EXPECT_EQ(0u, spdy_stream1->stream_id());
4732 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4733 spdy_stream1->SetDelegate(&delegate1);
4734
4735 EXPECT_EQ(0u, session->num_active_streams());
4736 EXPECT_EQ(1u, session->num_created_streams());
4737 EXPECT_EQ(0u, session->num_pushed_streams());
4738 EXPECT_EQ(0u, session->num_active_pushed_streams());
4739
4740 scoped_ptr<SpdyHeaderBlock> headers(
4741 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4742 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4743 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4744
4745 // Run until 1st stream is activated.
4746 EXPECT_EQ(0u, delegate1.stream_id());
4747 data.RunFor(1);
4748 EXPECT_EQ(1u, delegate1.stream_id());
4749 EXPECT_EQ(1u, session->num_active_streams());
4750 EXPECT_EQ(0u, session->num_created_streams());
4751 EXPECT_EQ(0u, session->num_pushed_streams());
4752 EXPECT_EQ(0u, session->num_active_pushed_streams());
4753
4754 // Run until pushed stream is created.
4755 data.RunFor(1);
4756 EXPECT_EQ(2u, session->num_active_streams());
4757 EXPECT_EQ(0u, session->num_created_streams());
4758 EXPECT_EQ(1u, session->num_pushed_streams());
4759 EXPECT_EQ(1u, session->num_active_pushed_streams());
4760
4761 // Reset incoming pushed stream.
4762 data.RunFor(2);
4763 EXPECT_EQ(2u, session->num_active_streams());
4764 EXPECT_EQ(0u, session->num_created_streams());
4765 EXPECT_EQ(1u, session->num_pushed_streams());
4766 EXPECT_EQ(1u, session->num_active_pushed_streams());
4767
4768 // Read EOF.
4769 data.RunFor(1);
4770 }
4771
4772 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4773 // Streams in reserved remote state exist only in SPDY4.
4774 if (spdy_util_.spdy_version() < SPDY4)
4775 return;
4776
4777 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4778 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4779 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4780 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4781 push_headers.get());
4782 scoped_ptr<SpdyFrame> push_b(
4783 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4784 scoped_ptr<SpdyFrame> headers_b(
4785 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4786 MockRead reads[] = {
4787 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4788 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4789 };
4790
4791 scoped_ptr<SpdyFrame> req(
4792 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4793 scoped_ptr<SpdyFrame> rst(
4794 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4795 MockWrite writes[] = {
4796 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4797 };
4798
4799 DeterministicSocketData data(
4800 reads, arraysize(reads), writes, arraysize(writes));
4801 MockConnect connect_data(SYNCHRONOUS, OK);
4802 data.set_connect_data(connect_data);
4803 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4804
4805 CreateDeterministicNetworkSession();
4806
4807 base::WeakPtr<SpdySession> session =
4808 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4809 session->set_max_concurrent_pushed_streams(1);
4810
4811 GURL url1(kDefaultURL);
4812 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4813 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4814 ASSERT_TRUE(spdy_stream1.get() != NULL);
4815 EXPECT_EQ(0u, spdy_stream1->stream_id());
4816 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4817 spdy_stream1->SetDelegate(&delegate1);
4818
4819 EXPECT_EQ(0u, session->num_active_streams());
4820 EXPECT_EQ(1u, session->num_created_streams());
4821 EXPECT_EQ(0u, session->num_pushed_streams());
4822 EXPECT_EQ(0u, session->num_active_pushed_streams());
4823
4824 scoped_ptr<SpdyHeaderBlock> headers(
4825 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4826 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4827 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4828
4829 // Run until 1st stream is activated.
4830 EXPECT_EQ(0u, delegate1.stream_id());
4831 data.RunFor(1);
4832 EXPECT_EQ(1u, delegate1.stream_id());
4833 EXPECT_EQ(1u, session->num_active_streams());
4834 EXPECT_EQ(0u, session->num_created_streams());
4835 EXPECT_EQ(0u, session->num_pushed_streams());
4836 EXPECT_EQ(0u, session->num_active_pushed_streams());
4837
4838 // Run until pushed stream is created.
4839 data.RunFor(1);
4840 EXPECT_EQ(2u, session->num_active_streams());
4841 EXPECT_EQ(0u, session->num_created_streams());
4842 EXPECT_EQ(1u, session->num_pushed_streams());
4843 EXPECT_EQ(1u, session->num_active_pushed_streams());
4844
4845 // Accept promised stream. It should not count towards pushed stream limit.
4846 data.RunFor(1);
4847 EXPECT_EQ(3u, session->num_active_streams());
4848 EXPECT_EQ(0u, session->num_created_streams());
4849 EXPECT_EQ(2u, session->num_pushed_streams());
4850 EXPECT_EQ(1u, session->num_active_pushed_streams());
4851
4852 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4853 // while we accept only one.
4854 data.RunFor(2);
4855 EXPECT_EQ(2u, session->num_active_streams());
4856 EXPECT_EQ(0u, session->num_created_streams());
4857 EXPECT_EQ(1u, session->num_pushed_streams());
4858 EXPECT_EQ(1u, session->num_active_pushed_streams());
4859
4860 // Read EOF.
4861 data.RunFor(1);
4862 }
4863
4864 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4865 // Streams in reserved remote state exist only in SPDY4.
4866 if (spdy_util_.spdy_version() < SPDY4)
4867 return;
4868
4869 const char kPushedUrl[] = "http://www.google.com/a.dat";
4870 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4871 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4872 scoped_ptr<SpdyFrame> push_promise(
4873 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4874 scoped_ptr<SpdyFrame> headers_frame(
4875 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4876 MockRead reads[] = {
4877 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4878 MockRead(ASYNC, 0, 4),
4879 };
4880
4881 scoped_ptr<SpdyFrame> req(
4882 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4883 scoped_ptr<SpdyFrame> rst(
4884 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4885 MockWrite writes[] = {
4886 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4887 };
4888
4889 DeterministicSocketData data(
4890 reads, arraysize(reads), writes, arraysize(writes));
4891 MockConnect connect_data(SYNCHRONOUS, OK);
4892 data.set_connect_data(connect_data);
4893 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4894
4895 CreateDeterministicNetworkSession();
4896
4897 base::WeakPtr<SpdySession> session =
4898 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4899
4900 GURL url1(kDefaultURL);
4901 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4902 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4903 ASSERT_TRUE(spdy_stream1.get() != NULL);
4904 EXPECT_EQ(0u, spdy_stream1->stream_id());
4905 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4906 spdy_stream1->SetDelegate(&delegate1);
4907
4908 EXPECT_EQ(0u, session->num_active_streams());
4909 EXPECT_EQ(1u, session->num_created_streams());
4910 EXPECT_EQ(0u, session->num_pushed_streams());
4911 EXPECT_EQ(0u, session->num_active_pushed_streams());
4912
4913 scoped_ptr<SpdyHeaderBlock> headers(
4914 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4915 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4916 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4917
4918 // Run until 1st stream is activated.
4919 EXPECT_EQ(0u, delegate1.stream_id());
4920 data.RunFor(1);
4921 EXPECT_EQ(1u, delegate1.stream_id());
4922 EXPECT_EQ(1u, session->num_active_streams());
4923 EXPECT_EQ(0u, session->num_created_streams());
4924 EXPECT_EQ(0u, session->num_pushed_streams());
4925 EXPECT_EQ(0u, session->num_active_pushed_streams());
4926
4927 // Run until pushed stream is created.
4928 data.RunFor(1);
4929 EXPECT_EQ(2u, session->num_active_streams());
4930 EXPECT_EQ(0u, session->num_created_streams());
4931 EXPECT_EQ(1u, session->num_pushed_streams());
4932 EXPECT_EQ(0u, session->num_active_pushed_streams());
4933
4934 base::WeakPtr<SpdyStream> pushed_stream;
4935 int rv =
4936 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4937 ASSERT_EQ(OK, rv);
4938 ASSERT_TRUE(pushed_stream.get() != NULL);
4939 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4940 pushed_stream->SetDelegate(&delegate2);
4941
4942 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4943 // that all our counters are in consistent state.
4944 data.RunFor(1);
4945 EXPECT_EQ(1u, session->num_active_streams());
4946 EXPECT_EQ(0u, session->num_created_streams());
4947 EXPECT_EQ(0u, session->num_pushed_streams());
4948 EXPECT_EQ(0u, session->num_active_pushed_streams());
4949
4950 // Read EOF.
4951 data.RunFor(2);
4952 }
4953
4612 TEST(MapFramerErrorToProtocolError, MapsValues) { 4954 TEST(MapFramerErrorToProtocolError, MapsValues) {
4613 CHECK_EQ( 4955 CHECK_EQ(
4614 SPDY_ERROR_INVALID_CONTROL_FRAME, 4956 SPDY_ERROR_INVALID_CONTROL_FRAME,
4615 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME)); 4957 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4616 CHECK_EQ( 4958 CHECK_EQ(
4617 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS, 4959 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4618 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS)); 4960 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4619 CHECK_EQ( 4961 CHECK_EQ(
4620 SPDY_ERROR_GOAWAY_FRAME_CORRUPT, 4962 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4621 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT)); 4963 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
(...skipping 30 matching lines...) Expand all
4652 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, 4994 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
4653 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR)); 4995 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
4654 CHECK_EQ(GOAWAY_COMPRESSION_ERROR, 4996 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
4655 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR)); 4997 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
4656 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR, 4998 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
4657 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR)); 4999 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
4658 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED)); 5000 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
4659 } 5001 }
4660 5002
4661 } // namespace net 5003 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_session.cc ('k') | net/spdy/spdy_stream_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698