diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-01 16:13:05 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-01 16:13:05 +0000 |
commit | b40f7faf5982af2c779be947864701a64e4943b6 (patch) | |
tree | f78f5fb9a1f2f254120623c37aaad21d2fc9aa9d /net | |
parent | 01e9bb094b3b16a094cf446429bfcb9a4cc0a33d (diff) | |
download | chromium_src-b40f7faf5982af2c779be947864701a64e4943b6.zip chromium_src-b40f7faf5982af2c779be947864701a64e4943b6.tar.gz chromium_src-b40f7faf5982af2c779be947864701a64e4943b6.tar.bz2 |
[SPDY] Send HTTP/2 connection prefix for HTTP/2 connections
Refactor sending of initial data. In particular, rename
SpdySession::SendInitialSettings() to SendInitialData() and move the
check of enable_sending_initial_data_ (also renamed) to its caller.
Fix bug in ProcessPendingStreamRequests() where the max concurrent
stream limit wasn't being obeyed.
HTTP/2 frame types will be used in an upcoming CL.
BUG=265815
R=rch@chromium.org
Review URL: https://codereview.chromium.org/21095004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215046 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/spdy/spdy_network_transaction_unittest.cc | 38 | ||||
-rw-r--r-- | net/spdy/spdy_session.cc | 140 | ||||
-rw-r--r-- | net/spdy/spdy_session.h | 22 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.cc | 4 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.h | 2 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc | 299 | ||||
-rw-r--r-- | net/spdy/spdy_test_util_common.cc | 10 | ||||
-rw-r--r-- | net/spdy/spdy_test_util_common.h | 2 | ||||
-rw-r--r-- | net/spdy/spdy_websocket_stream_unittest.cc | 56 |
9 files changed, 300 insertions, 273 deletions
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 2f65151..98c4d13 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -4276,9 +4276,13 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { net_log, GetParam(), NULL); helper.RunPreTestSetup(); + SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); + + SpdySessionPoolPeer pool_peer(spdy_session_pool); + pool_peer.SetEnableSendingInitialData(true); + // Verify that no settings exist initially. HostPortPair host_port_pair("www.google.com", helper.port()); - SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings( host_port_pair).empty()); @@ -4304,7 +4308,20 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings( host_port_pair).size()); - // Construct the SETTINGS frame. + // Construct the initial SETTINGS frame. + SettingsMap initial_settings; + initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = + SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); + scoped_ptr<SpdyFrame> initial_settings_frame( + spdy_util_.ConstructSpdySettings(initial_settings)); + + // Construct the initial window update. + scoped_ptr<SpdyFrame> initial_window_update( + spdy_util_.ConstructSpdyWindowUpdate( + kSessionFlowControlStreamId, + kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); + + // Construct the persisted SETTINGS frame. const SettingsMap& settings = spdy_session_pool->http_server_properties()->GetSpdySettings( host_port_pair); @@ -4315,10 +4332,19 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { scoped_ptr<SpdyFrame> req( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); - MockWrite writes[] = { - CreateMockWrite(*settings_frame), - CreateMockWrite(*req), + std::vector<MockWrite> writes; + if (GetParam().protocol == kProtoHTTP2Draft04) { + writes.push_back( + MockWrite(ASYNC, + kHttp2ConnectionHeaderPrefix, + kHttp2ConnectionHeaderPrefixSize)); + } + writes.push_back(CreateMockWrite(*initial_settings_frame)); + if (GetParam().protocol >= kProtoSPDY31) { + writes.push_back(CreateMockWrite(*initial_window_update)); }; + writes.push_back(CreateMockWrite(*settings_frame)); + writes.push_back(CreateMockWrite(*req)); // Construct the reply. scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock()); @@ -4335,7 +4361,7 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { }; DelayedSocketData data(2, reads, arraysize(reads), - writes, arraysize(writes)); + vector_as_array(&writes), writes.size()); helper.AddData(&data); helper.RunDefaultTest(); helper.VerifyDataConsumed(); diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index d085a4d..8a730ce 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -205,9 +205,6 @@ base::Value* NetLogSpdyGoAwayCallback(SpdyStreamId last_stream_id, return dict; } -// Maximum number of concurrent streams we will create, unless the server -// sends a SETTINGS frame with a different value. -const size_t kInitialMaxConcurrentStreams = 100; // The maximum number of concurrent streams we will ever create. Even if // the server permits more, we will never exceed this limit. const size_t kMaxConcurrentStreamLimit = 256; @@ -320,7 +317,7 @@ SpdySession::SpdySession( const SpdySessionKey& spdy_session_key, const base::WeakPtr<HttpServerProperties>& http_server_properties, bool verify_domain_authentication, - bool enable_sending_initial_settings, + bool enable_sending_initial_data, bool enable_credential_frames, bool enable_compression, bool enable_ping_based_connection_checking, @@ -364,6 +361,7 @@ SpdySession::SpdySession( next_ping_id_(1), last_activity_time_(time_func()), check_ping_status_pending_(false), + send_connection_header_prefix_(false), flow_control_state_(FLOW_CONTROL_NONE), stream_initial_send_window_size_(kSpdyStreamInitialWindowSize), stream_initial_recv_window_size_(stream_initial_recv_window_size == 0 ? @@ -374,7 +372,7 @@ SpdySession::SpdySession( session_unacked_recv_window_bytes_(0), net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), verify_domain_authentication_(verify_domain_authentication), - enable_sending_initial_settings_(enable_sending_initial_settings), + enable_sending_initial_data_(enable_sending_initial_data), enable_credential_frames_(enable_credential_frames), enable_compression_(enable_compression), enable_ping_based_connection_checking_( @@ -458,6 +456,9 @@ Error SpdySession::InitializeWithSocket( host_port_pair().ToString())); } + if (protocol_ == kProtoHTTP2Draft04) + send_connection_header_prefix_ = true; + if (protocol_ >= kProtoSPDY31) { flow_control_state_ = FLOW_CONTROL_STREAM_AND_SESSION; session_send_window_size_ = kSpdySessionInitialWindowSize; @@ -490,7 +491,8 @@ Error SpdySession::InitializeWithSocket( if (error == OK) { DCHECK_NE(availability_state_, STATE_CLOSED); connection_->AddLayeredPool(this); - SendInitialSettings(); + if (enable_sending_initial_data_) + SendInitialData(); pool_ = pool; } else { DcheckClosed(); @@ -672,29 +674,37 @@ void SpdySession::CancelStreamRequest(SpdyStreamRequest* request) { } void SpdySession::ProcessPendingStreamRequests() { - while (!max_concurrent_streams_ || - (active_streams_.size() + created_streams_.size() < - max_concurrent_streams_)) { - bool no_pending_create_streams = true; - for (int i = NUM_PRIORITIES - 1; i >= MINIMUM_PRIORITY; --i) { - if (!pending_create_stream_queues_[i].empty()) { - SpdyStreamRequest* pending_request = - pending_create_stream_queues_[i].front(); - CHECK(pending_request); - pending_create_stream_queues_[i].pop_front(); - no_pending_create_streams = false; - DCHECK(!ContainsKey(pending_stream_request_completions_, - pending_request)); - pending_stream_request_completions_.insert(pending_request); - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&SpdySession::CompleteStreamRequest, - weak_factory_.GetWeakPtr(), pending_request)); - break; - } + // Like |max_concurrent_streams_|, 0 means infinite for + // |max_requests_to_process|. + size_t max_requests_to_process = 0; + if (max_concurrent_streams_ != 0) { + max_requests_to_process = + max_concurrent_streams_ - + (active_streams_.size() + created_streams_.size()); + } + for (size_t i = 0; + max_requests_to_process == 0 || i < max_requests_to_process; ++i) { + bool processed_request = false; + for (int j = NUM_PRIORITIES - 1; j >= MINIMUM_PRIORITY; --j) { + if (pending_create_stream_queues_[j].empty()) + continue; + + SpdyStreamRequest* pending_request = + pending_create_stream_queues_[j].front(); + CHECK(pending_request); + pending_create_stream_queues_[j].pop_front(); + processed_request = true; + DCHECK(!ContainsKey(pending_stream_request_completions_, + pending_request)); + pending_stream_request_completions_.insert(pending_request); + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&SpdySession::CompleteStreamRequest, + weak_factory_.GetWeakPtr(), pending_request)); + break; } - if (no_pending_create_streams) - return; // there were no streams in any queue + if (!processed_request) + break; } } @@ -2348,29 +2358,38 @@ void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, stream_id, delta_window_size, it->second.stream->priority()); } -void SpdySession::SendInitialSettings() { +void SpdySession::SendInitialData() { + DCHECK(enable_sending_initial_data_); DCHECK_NE(availability_state_, STATE_CLOSED); + if (send_connection_header_prefix_) { + DCHECK_EQ(protocol_, kProtoHTTP2Draft04); + scoped_ptr<SpdyFrame> connection_header_prefix_frame( + new SpdyFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), + kHttp2ConnectionHeaderPrefixSize, + false /* take_ownership */)); + // Count the prefix as part of the subsequent SETTINGS frame. + EnqueueSessionWrite(HIGHEST, SETTINGS, + connection_header_prefix_frame.Pass()); + } + // First, notify the server about the settings they should use when // communicating with us. - if (GetProtocolVersion() >= 2 && enable_sending_initial_settings_) { - SettingsMap settings_map; - // Create a new settings frame notifying the sever of our - // max_concurrent_streams_ and initial window size. - settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); - if (GetProtocolVersion() > 2 && - stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { - settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, - stream_initial_recv_window_size_); - } - SendSettings(settings_map); - } + SettingsMap settings_map; + // Create a new settings frame notifying the server of our + // max concurrent streams and initial window size. + settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = + SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); + if (flow_control_state_ >= FLOW_CONTROL_STREAM && + stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { + settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = + SettingsFlagsAndValue(SETTINGS_FLAG_NONE, + stream_initial_recv_window_size_); + } + SendSettings(settings_map); // Next, notify the server about our initial recv window size. - if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION && - enable_sending_initial_settings_) { + if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { // Bump up the receive window size to the real initial value. This // has to go here since the WINDOW_UPDATE frame sent by // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. @@ -2382,30 +2401,27 @@ void SpdySession::SendInitialSettings() { kDefaultInitialRecvWindowSize - session_recv_window_size_); } - // Finally, notify the server about the settings they have previously - // told us to use when communicating with them. - const SettingsMap& settings_map = + // Finally, notify the server about the settings they have + // previously told us to use when communicating with them (after + // applying them). + const SettingsMap& server_settings_map = http_server_properties_->GetSpdySettings(host_port_pair()); - if (settings_map.empty()) + if (server_settings_map.empty()) return; - const SpdySettingsIds id = SETTINGS_CURRENT_CWND; - SettingsMap::const_iterator it = settings_map.find(id); - uint32 value = 0; - if (it != settings_map.end()) - value = it->second.second; - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", value, 1, 200, 100); + SettingsMap::const_iterator it = + server_settings_map.find(SETTINGS_CURRENT_CWND); + uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0; + UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100); - const SettingsMap& settings_map_new = - http_server_properties_->GetSpdySettings(host_port_pair()); - for (SettingsMap::const_iterator i = settings_map_new.begin(), - end = settings_map_new.end(); i != end; ++i) { - const SpdySettingsIds new_id = i->first; - const uint32 new_val = i->second.second; + for (SettingsMap::const_iterator it = server_settings_map.begin(); + it != server_settings_map.end(); ++it) { + const SpdySettingsIds new_id = it->first; + const uint32 new_val = it->second.second; HandleSetting(new_id, new_val); } - SendSettings(settings_map_new); + SendSettings(server_settings_map); } diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index c2d5b10..c6a22e6 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -49,6 +49,10 @@ const int kMss = 1430; // The 8 is the size of the SPDY frame header. const int kMaxSpdyFrameChunkSize = (2 * kMss) - 8; +// Maximum number of concurrent streams we will create, unless the server +// sends a SETTINGS frame with a different value. +const size_t kInitialMaxConcurrentStreams = 100; + // Specifies the maxiumum concurrent streams server could send (via push). const int kMaxConcurrentPushedStreams = 1000; @@ -202,7 +206,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface, SpdySession(const SpdySessionKey& spdy_session_key, const base::WeakPtr<HttpServerProperties>& http_server_properties, bool verify_domain_authentication, - bool enable_sending_initial_settings, + bool enable_sending_initial_data, bool enable_credential_frames, bool enable_compression, bool enable_ping_based_connection_checking, @@ -646,10 +650,15 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface, int DoWrite(); int DoWriteComplete(int result); - // Send relevant SETTINGS. This is generally called on connection setup. - void SendInitialSettings(); + // TODO(akalin): Rename the Send* and Write* functions below to + // Enqueue*. + + // Send initial data. Called when a connection is successfully + // established in InitializeWithSocket() and + // |enable_sending_initial_data_| is true. + void SendInitialData(); - // Helper method to send SETTINGS a frame. + // Helper method to send a SETTINGS frame. void SendSettings(const SettingsMap& settings); // Handle SETTING. Either when we send settings, or when we receive a @@ -1056,6 +1065,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface, // status. bool check_ping_status_pending_; + // Whether to send the (HTTP/2) connection header prefix. + bool send_connection_header_prefix_; + // The (version-dependent) flow control state. FlowControlState flow_control_state_; @@ -1085,7 +1097,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface, // Outside of tests, these should always be true. bool verify_domain_authentication_; - bool enable_sending_initial_settings_; + bool enable_sending_initial_data_; bool enable_credential_frames_; bool enable_compression_; bool enable_ping_based_connection_checking_; diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index 185ec23..9e47f3f 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -46,7 +46,7 @@ SpdySessionPool::SpdySessionPool( ssl_config_service_(ssl_config_service), resolver_(resolver), verify_domain_authentication_(true), - enable_sending_initial_settings_(true), + enable_sending_initial_data_(true), force_single_domain_(force_single_domain), enable_ip_pooling_(enable_ip_pooling), enable_credential_frames_(enable_credential_frames), @@ -103,7 +103,7 @@ net::Error SpdySessionPool::CreateAvailableSessionFromSocket( new SpdySession(key, http_server_properties_, verify_domain_authentication_, - enable_sending_initial_settings_, + enable_sending_initial_data_, enable_credential_frames_, enable_compression_, enable_ping_based_connection_checking_, diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index c27d6d5..812b7bd 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -211,7 +211,7 @@ class NET_EXPORT SpdySessionPool // Defaults to true. May be controlled via SpdySessionPoolPeer for tests. bool verify_domain_authentication_; - bool enable_sending_initial_settings_; + bool enable_sending_initial_data_; bool force_single_domain_; bool enable_ip_pooling_; bool enable_credential_frames_; diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index ea7a6d1..6388bf8 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -909,43 +909,27 @@ TEST_P(SpdySessionTest, FailedPing) { EXPECT_EQ(NULL, spdy_stream1.get()); } -// Start with max concurrent streams set to 1. Request two streams. Receive a -// settings frame setting max concurrent streams to 2. Have the callback -// release the stream, which releases its reference (the last) to the session. -// Make sure nothing blows up. -// http://crbug.com/57331 +// Request kInitialMaxConcurrentStreams + 1 streams. Receive a +// settings frame increasing the max concurrent streams by 1. Make +// sure nothing blows up. This is a regression test for +// http://crbug.com/57331 . TEST_P(SpdySessionTest, OnSettings) { session_deps_.host_resolver->set_synchronous_mode(true); const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS; - SettingsMap initial_settings; - const uint32 initial_max_concurrent_streams = 1; - initial_settings[kSpdySettingsIds] = - SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED, - initial_max_concurrent_streams); - scoped_ptr<SpdyFrame> initial_settings_frame( - spdy_util_.ConstructSpdySettings(initial_settings)); - MockWrite writes[] = { - CreateMockWrite(*initial_settings_frame, 0), - }; - SettingsMap new_settings; - const uint32 max_concurrent_streams = 2; + const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1; new_settings[kSpdySettingsIds] = SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); - - // Set up the socket so we read a SETTINGS frame that raises max concurrent - // streams to 2. scoped_ptr<SpdyFrame> settings_frame( spdy_util_.ConstructSpdySettings(new_settings)); MockRead reads[] = { - CreateMockRead(*settings_frame, 1), - MockRead(ASYNC, 0, 2), + CreateMockRead(*settings_frame, 0), + MockRead(ASYNC, 0, 1), }; - DeterministicSocketData data( - reads, arraysize(reads), writes, arraysize(writes)); + DeterministicSocketData data(reads, arraysize(reads), NULL, 0); MockConnect connect_data(SYNCHRONOUS, OK); data.set_connect_data(connect_data); session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); @@ -955,21 +939,16 @@ TEST_P(SpdySessionTest, OnSettings) { CreateDeterministicNetworkSession(); - // Initialize the SpdySetting with 1 max concurrent streams. - spdy_session_pool_->http_server_properties()->SetSpdySetting( - test_host_port_pair_, - kSpdySettingsIds, - SETTINGS_FLAG_PLEASE_PERSIST, - initial_max_concurrent_streams); - base::WeakPtr<SpdySession> session = CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); - // Create 2 streams. First will succeed. Second will be pending. - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session, test_url_, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); + // Create the maximum number of concurrent streams. + for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) { + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, test_url_, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream != NULL); + } StreamReleaserCallback stream_releaser; SpdyStreamRequest request; @@ -979,7 +958,7 @@ TEST_P(SpdySessionTest, OnSettings) { BoundNetLog(), stream_releaser.MakeCallback(&request))); - data.RunFor(2); + data.RunFor(1); EXPECT_EQ(OK, stream_releaser.WaitForResult()); @@ -987,43 +966,27 @@ TEST_P(SpdySessionTest, OnSettings) { EXPECT_TRUE(session == NULL); } -// Start with max concurrent streams set to 1 (that is persisted). Receive a -// settings frame setting max concurrent streams to 2 and which also clears the -// persisted data. Verify that persisted data is correct. +// Start with a persisted value for max concurrent streams. Receive a +// settings frame increasing the max concurrent streams by 1 and which +// also clears the persisted data. Verify that persisted data is +// correct. TEST_P(SpdySessionTest, ClearSettings) { session_deps_.host_resolver->set_synchronous_mode(true); - const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS; - - SettingsMap initial_settings; - const uint32 initial_max_concurrent_streams = 1; - initial_settings[kSpdySettingsIds] = - SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED, - initial_max_concurrent_streams); - scoped_ptr<SpdyFrame> initial_settings_frame( - spdy_util_.ConstructSpdySettings(initial_settings)); - MockWrite writes[] = { - CreateMockWrite(*initial_settings_frame, 0), - }; - SettingsMap new_settings; - const uint32 max_concurrent_streams = 2; - new_settings[kSpdySettingsIds] = + const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1; + new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); - - // Set up the socket so we read a SETTINGS frame that raises max concurrent - // streams to 2. scoped_ptr<SpdyFrame> settings_frame( spdy_util_.ConstructSpdySettings(new_settings)); uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version()); MockRead reads[] = { - CreateMockRead(*settings_frame, 1), - MockRead(ASYNC, 0, 2), + CreateMockRead(*settings_frame, 0), + MockRead(ASYNC, 0, 1), }; - DeterministicSocketData data( - reads, arraysize(reads), writes, arraysize(writes)); + DeterministicSocketData data(reads, arraysize(reads), NULL, 0); MockConnect connect_data(SYNCHRONOUS, OK); data.set_connect_data(connect_data); session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); @@ -1033,24 +996,27 @@ TEST_P(SpdySessionTest, ClearSettings) { CreateDeterministicNetworkSession(); - // Initialize the SpdySetting with 1 max concurrent streams. + // Initialize the SpdySetting with the default. spdy_session_pool_->http_server_properties()->SetSpdySetting( test_host_port_pair_, - kSpdySettingsIds, + SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_FLAG_PLEASE_PERSIST, - initial_max_concurrent_streams); + kInitialMaxConcurrentStreams); - EXPECT_EQ(1u, spdy_session_pool_->http_server_properties()->GetSpdySettings( - test_host_port_pair_).size()); + EXPECT_FALSE( + spdy_session_pool_->http_server_properties()->GetSpdySettings( + test_host_port_pair_).empty()); base::WeakPtr<SpdySession> session = CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); - // Create 2 streams. First will succeed. Second will be pending. - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session, test_url_, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); + // Create the maximum number of concurrent streams. + for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) { + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, test_url_, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream != NULL); + } StreamReleaserCallback stream_releaser; @@ -1061,25 +1027,28 @@ TEST_P(SpdySessionTest, ClearSettings) { BoundNetLog(), stream_releaser.MakeCallback(&request))); - data.RunFor(2); + data.RunFor(1); EXPECT_EQ(OK, stream_releaser.WaitForResult()); // Make sure that persisted data is cleared. - EXPECT_EQ(0u, spdy_session_pool_->http_server_properties()->GetSpdySettings( - test_host_port_pair_).size()); + EXPECT_TRUE( + spdy_session_pool_->http_server_properties()->GetSpdySettings( + test_host_port_pair_).empty()); - // Make sure session's max_concurrent_streams is 2. - EXPECT_EQ(2u, session->max_concurrent_streams()); + // Make sure session's max_concurrent_streams is correct. + EXPECT_EQ(kInitialMaxConcurrentStreams + 1, + session->max_concurrent_streams()); data.RunFor(1); EXPECT_TRUE(session == NULL); } -// Start with max concurrent streams set to 1. Request two streams. When the -// first completes, have the callback close itself, which should trigger the -// second stream creation. Then cancel that one immediately. Don't crash. -// http://crbug.com/63532 +// Start with max concurrent streams set to 1. Request two streams. +// When the first completes, have the callback close its stream, which +// should trigger the second stream creation. Then cancel that one +// immediately. Don't crash. This is a regression test for +// http://crbug.com/63532 . TEST_P(SpdySessionTest, CancelPendingCreateStream) { session_deps_.host_resolver->set_synchronous_mode(true); @@ -1108,7 +1077,15 @@ TEST_P(SpdySessionTest, CancelPendingCreateStream) { base::WeakPtr<SpdySession> session = CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); - // Create 2 streams. First will succeed. Second will be pending. + // Leave room for only one more stream to be created. + for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) { + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, test_url_, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream != NULL); + } + + // Create 2 more streams. First will succeed. Second will be pending. base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog()); @@ -1136,7 +1113,7 @@ TEST_P(SpdySessionTest, CancelPendingCreateStream) { base::MessageLoop::current()->RunUntilIdle(); } -TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) { +TEST_P(SpdySessionTest, SendInitialDataOnNewSession) { session_deps_.host_resolver->set_synchronous_mode(true); MockRead reads[] = { @@ -1160,61 +1137,31 @@ TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) { spdy_util_.ConstructSpdyWindowUpdate( kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); - MockWrite writes[] = { - CreateMockWrite(*settings_frame), - CreateMockWrite(*initial_window_update), - }; - session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize; - int num_writes = arraysize(writes); - // We don't have session windows for SPDY versions less than 3.1. - if (spdy_util_.protocol() < kProtoSPDY31) { - --num_writes; + std::vector<MockWrite> writes; + if (GetParam() == kProtoHTTP2Draft04) { + writes.push_back( + MockWrite(ASYNC, + kHttp2ConnectionHeaderPrefix, + kHttp2ConnectionHeaderPrefixSize)); } - - StaticSocketDataProvider data(reads, arraysize(reads), writes, num_writes); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - SpdySessionPoolPeer pool_peer(spdy_session_pool_); - pool_peer.EnableSendingInitialSettings(true); - - base::WeakPtr<SpdySession> session = - CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); - - base::MessageLoop::current()->RunUntilIdle(); - EXPECT_TRUE(data.at_write_eof()); -} - -TEST_P(SpdySessionTest, SendSettingsOnNewSession) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. + writes.push_back(CreateMockWrite(*settings_frame)); + if (GetParam() >= kProtoSPDY31) { + writes.push_back(CreateMockWrite(*initial_window_update)); }; - // Create the bogus setting that we want to verify is sent out. - // Note that it will be marked as SETTINGS_FLAG_PERSISTED when sent out. But - // to persist it into the HttpServerProperties, we need to mark as - // SETTINGS_FLAG_PLEASE_PERSIST. - SettingsMap settings; - const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_UPLOAD_BANDWIDTH; - const uint32 kBogusSettingValue = 0xCDCD; - settings[kSpdySettingsIds1] = - SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED, kBogusSettingValue); - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> settings_frame( - spdy_util_.ConstructSpdySettings(settings)); - MockWrite writes[] = { - CreateMockWrite(*settings_frame), - }; + SettingsMap server_settings; + const uint32 initial_max_concurrent_streams = 1; + server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = + SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED, + initial_max_concurrent_streams); + scoped_ptr<SpdyFrame> server_settings_frame( + spdy_util_.ConstructSpdySettings(server_settings)); + writes.push_back(CreateMockWrite(*server_settings_frame)); - StaticSocketDataProvider data( - reads, arraysize(reads), writes, arraysize(writes)); + session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize; + + StaticSocketDataProvider data(reads, arraysize(reads), + vector_as_array(&writes), writes.size()); data.set_connect_data(connect_data); session_deps_.socket_factory->AddSocketDataProvider(&data); @@ -1225,9 +1172,12 @@ TEST_P(SpdySessionTest, SendSettingsOnNewSession) { spdy_session_pool_->http_server_properties()->SetSpdySetting( test_host_port_pair_, - kSpdySettingsIds1, + SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_FLAG_PLEASE_PERSIST, - kBogusSettingValue); + initial_max_concurrent_streams); + + SpdySessionPoolPeer pool_peer(spdy_session_pool_); + pool_peer.SetEnableSendingInitialData(true); base::WeakPtr<SpdySession> session = CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); @@ -2085,7 +2035,8 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { SPDY_REQUEST_RESPONSE_STREAM, session, url3, LOWEST, BoundNetLog(), callback3.callback())); - EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(1u, session->num_created_streams()); EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST)); scoped_ptr<SpdyHeaderBlock> headers( @@ -2093,15 +2044,23 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); - // Run until 1st stream is closed and 2nd one is opened. + // Run until 1st stream is activated and then closed. EXPECT_EQ(0u, delegate1.stream_id()); data.RunFor(3); - // Pump loop for SpdySession::ProcessPendingStreamRequests(). - base::MessageLoop::current()->RunUntilIdle(); EXPECT_EQ(NULL, spdy_stream1.get()); EXPECT_EQ(1u, delegate1.stream_id()); - EXPECT_EQ(2u, session->num_active_streams() + session->num_created_streams()); - EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); + + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(0u, session->num_created_streams()); + EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST)); + + // Pump loop for SpdySession::ProcessPendingStreamRequests() to + // create the 2nd stream. + base::MessageLoop::current()->RunUntilIdle(); + + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(1u, session->num_created_streams()); + EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST)); base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream(); test::StreamDelegateDoNothing delegate2(stream2); @@ -2111,12 +2070,22 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); EXPECT_TRUE(stream2->HasUrlFromHeaders()); - // Run until 2nd stream is closed. + // Run until 2nd stream is activated and then closed. EXPECT_EQ(0u, delegate2.stream_id()); data.RunFor(3); EXPECT_EQ(NULL, stream2.get()); EXPECT_EQ(3u, delegate2.stream_id()); - EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); + + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(0u, session->num_created_streams()); + EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); + + // Pump loop for SpdySession::ProcessPendingStreamRequests() to + // create the 3rd stream. + base::MessageLoop::current()->RunUntilIdle(); + + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(1u, session->num_created_streams()); EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream(); @@ -2127,11 +2096,14 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND); EXPECT_TRUE(stream3->HasUrlFromHeaders()); + // Run until 2nd stream is activated and then closed. EXPECT_EQ(0u, delegate3.stream_id()); data.RunFor(3); EXPECT_EQ(NULL, stream3.get()); EXPECT_EQ(5u, delegate3.stream_id()); - EXPECT_EQ(0u, session->num_active_streams() + session->num_created_streams()); + + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(0u, session->num_created_streams()); EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); data.RunFor(1); @@ -2155,16 +2127,17 @@ TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) { CreateNetworkSession(); - // Initialize the SpdySetting with 1 max concurrent streams. - spdy_session_pool_->http_server_properties()->SetSpdySetting( - test_host_port_pair_, - SETTINGS_MAX_CONCURRENT_STREAMS, - SETTINGS_FLAG_PLEASE_PERSIST, - 1); - base::WeakPtr<SpdySession> session = CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); + // Leave room for only one more stream to be created. + for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) { + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, test_url_, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream != NULL); + } + GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, @@ -2188,30 +2161,36 @@ TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) { SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(), callback3.callback())); - EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams()); EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST)); - // Cancel the first stream, this will allow the second stream to be created. + // Cancel the first stream; this will allow the second stream to be created. EXPECT_TRUE(spdy_stream1.get() != NULL); spdy_stream1->Cancel(); EXPECT_EQ(NULL, spdy_stream1.get()); - callback2.WaitForResult(); - EXPECT_EQ(2u, session->num_active_streams() + session->num_created_streams()); - EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); + EXPECT_EQ(OK, callback2.WaitForResult()); + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams()); + EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST)); - // Cancel the second stream, this will allow the third stream to be created. + // Cancel the second stream; this will allow the third stream to be created. base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream(); spdy_stream2->Cancel(); EXPECT_EQ(NULL, spdy_stream2.get()); - EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); + + EXPECT_EQ(OK, callback3.WaitForResult()); + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams()); EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); // Cancel the third stream. base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream(); spdy_stream3->Cancel(); EXPECT_EQ(NULL, spdy_stream3.get()); - EXPECT_EQ(0u, session->num_active_streams() + session->num_created_streams()); + EXPECT_EQ(0u, session->num_active_streams()); + EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams()); EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST)); } diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 4c52751..4383db0 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc @@ -401,7 +401,7 @@ HttpNetworkSession* SpdySessionDependencies::SpdyCreateSession( params.client_socket_factory = session_deps->socket_factory.get(); HttpNetworkSession* http_session = new HttpNetworkSession(params); SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool()); - pool_peer.EnableSendingInitialSettings(false); + pool_peer.SetEnableSendingInitialData(false); return http_session; } @@ -413,7 +413,7 @@ HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic( session_deps->deterministic_socket_factory.get(); HttpNetworkSession* http_session = new HttpNetworkSession(params); SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool()); - pool_peer.EnableSendingInitialSettings(false); + pool_peer.SetEnableSendingInitialData(false); return http_session; } @@ -476,7 +476,7 @@ SpdyURLRequestContext::SpdyURLRequestContext(NextProto protocol) scoped_refptr<HttpNetworkSession> network_session( new HttpNetworkSession(params)); SpdySessionPoolPeer pool_peer(network_session->spdy_session_pool()); - pool_peer.EnableSendingInitialSettings(false); + pool_peer.SetEnableSendingInitialData(false); storage_.set_http_transaction_factory(new HttpCache( network_session.get(), HttpCache::DefaultBackend::InMemory(0))); } @@ -686,8 +686,8 @@ void SpdySessionPoolPeer::DisableDomainAuthenticationVerification() { pool_->verify_domain_authentication_ = false; } -void SpdySessionPoolPeer::EnableSendingInitialSettings(bool enabled) { - pool_->enable_sending_initial_settings_ = enabled; +void SpdySessionPoolPeer::SetEnableSendingInitialData(bool enabled) { + pool_->enable_sending_initial_data_ = enabled; } SpdyTestUtil::SpdyTestUtil(NextProto protocol) diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index 7f5f2ab..aa833ff 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h @@ -280,7 +280,7 @@ class SpdySessionPoolPeer { void RemoveAliases(const SpdySessionKey& key); void DisableDomainAuthenticationVerification(); - void EnableSendingInitialSettings(bool enabled); + void SetEnableSendingInitialData(bool enabled); private: SpdySessionPool* const pool_; diff --git a/net/spdy/spdy_websocket_stream_unittest.cc b/net/spdy/spdy_websocket_stream_unittest.cc index f05b34e..e0661a0 100644 --- a/net/spdy/spdy_websocket_stream_unittest.cc +++ b/net/spdy/spdy_websocket_stream_unittest.cc @@ -238,23 +238,11 @@ class SpdyWebSocketStreamTest } void InitSession(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count, - bool throttling) { + MockWrite* writes, size_t writes_count) { data_.reset(new OrderedSocketData(reads, reads_count, writes, writes_count)); session_deps_.socket_factory->AddSocketDataProvider(data_.get()); http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); - SpdySessionPool* spdy_session_pool(http_session_->spdy_session_pool()); - - if (throttling) { - // Set max concurrent streams to 1. - spdy_session_pool->http_server_properties()->SetSpdySetting( - host_port_pair_, - spdy_settings_id_to_set_, - spdy_settings_flags_to_set_, - spdy_settings_value_to_set_); - } - session_ = CreateInsecureSpdySession( http_session_, spdy_session_key_, BoundNetLog()); } @@ -327,7 +315,7 @@ TEST_P(SpdyWebSocketStreamTest, Basic) { MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event. }; - InitSession(reads, arraysize(reads), writes, arraysize(writes), false); + InitSession(reads, arraysize(reads), writes, arraysize(writes)); SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnReceivedHeader( @@ -399,7 +387,7 @@ TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) { MockRead(ASYNC, ERR_IO_PENDING, 5) }; - InitSession(reads, arraysize(reads), writes, arraysize(writes), false); + InitSession(reads, arraysize(reads), writes, arraysize(writes)); SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnReceivedHeader( @@ -461,7 +449,7 @@ TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) { MockRead(ASYNC, ERR_IO_PENDING, 6) }; - InitSession(reads, arraysize(reads), writes, arraysize(writes), false); + InitSession(reads, arraysize(reads), writes, arraysize(writes)); SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnReceivedHeader( @@ -512,24 +500,27 @@ TEST_P(SpdyWebSocketStreamTest, IOPending) { scoped_ptr<SpdyFrame> settings_frame( spdy_util_.ConstructSpdySettings(spdy_settings_to_send_)); MockWrite writes[] = { - // Setting throttling make SpdySession send settings frame automatically. - CreateMockWrite(*settings_frame.get(), 1), - CreateMockWrite(*request_frame_.get(), 3), - CreateMockWrite(*message_frame_.get(), 6), - CreateMockWrite(*closing_frame_.get(), 9) + CreateMockWrite(*request_frame_.get(), 1), + CreateMockWrite(*message_frame_.get(), 3), + CreateMockWrite(*closing_frame_.get(), 5) }; MockRead reads[] = { - CreateMockRead(*settings_frame.get(), 2), - CreateMockRead(*response_frame_.get(), 4), - // Skip sequence 5 (I/O Pending) - CreateMockRead(*message_frame_.get(), 7), - // Skip sequence 8 (I/O Pending) - CreateMockRead(*closing_frame_.get(), 10), - MockRead(SYNCHRONOUS, 0, 11) // EOF cause OnCloseSpdyStream event. + CreateMockRead(*settings_frame.get(), 0), + CreateMockRead(*response_frame_.get(), 2), + CreateMockRead(*message_frame_.get(), 4), + CreateMockRead(*closing_frame_.get(), 6), + MockRead(SYNCHRONOUS, 0, 7) // EOF cause OnCloseSpdyStream event. }; - InitSession(reads, arraysize(reads), writes, arraysize(writes), true); + DeterministicSocketData data(reads, arraysize(reads), + writes, arraysize(writes)); + session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); + http_session_ = + SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); + + session_ = CreateInsecureSpdySession( + http_session_, spdy_session_key_, BoundNetLog()); // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another // WebSocketStream under test. @@ -542,6 +533,8 @@ TEST_P(SpdyWebSocketStreamTest, IOPending) { ASSERT_EQ(OK, block_stream->InitializeStream(block_url, HIGHEST, block_net_log)); + data.RunFor(1); + // Create a WebSocketStream under test. SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnCreated( @@ -566,6 +559,7 @@ TEST_P(SpdyWebSocketStreamTest, IOPending) { SendRequest(); + data.RunFor(7); completion_callback_.WaitForResult(); websocket_stream_.reset(); @@ -605,8 +599,8 @@ TEST_P(SpdyWebSocketStreamTest, IOPending) { // EOF close SPDY session. EXPECT_FALSE( HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); - EXPECT_TRUE(data()->at_read_eof()); - EXPECT_TRUE(data()->at_write_eof()); + EXPECT_TRUE(data.at_read_eof()); + EXPECT_TRUE(data.at_write_eof()); } } // namespace net |