diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-11 21:23:34 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-11 21:23:34 +0000 |
commit | 162deb8fa72342e8dae1c4793f9b6c4630af2a47 (patch) | |
tree | d6bbb6cf9d69e5c9e96158926368ed37b85f85c6 /net/spdy | |
parent | 3774f835ddbe5005ad49c5a1818b3fcbfff4f703 (diff) | |
download | chromium_src-162deb8fa72342e8dae1c4793f9b6c4630af2a47.zip chromium_src-162deb8fa72342e8dae1c4793f9b6c4630af2a47.tar.gz chromium_src-162deb8fa72342e8dae1c4793f9b6c4630af2a47.tar.bz2 |
[SPDY] Merge the SpdySession unit tests and parametrize them on a NextProto
Add (partial) support for SPDY/3.1 and SPDY/4a2 for SpdySession unit tests.
Add support for SPDY/4a2 for SpdyStream unit tests (which was mistakenly
not done in r203570).
BUG=226192
R=rch@chromium.org
Review URL: https://codereview.chromium.org/16434012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205637 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy')
-rw-r--r-- | net/spdy/spdy_session.h | 37 | ||||
-rw-r--r-- | net/spdy/spdy_session_spdy2_unittest.cc | 2498 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc (renamed from net/spdy/spdy_session_spdy3_unittest.cc) | 603 | ||||
-rw-r--r-- | net/spdy/spdy_stream_unittest.cc | 2 |
4 files changed, 357 insertions, 2783 deletions
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 37435c6..22b1edf 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -464,32 +464,21 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, private: friend class base::RefCounted<SpdySession>; friend class SpdyStreamRequest; - friend class SpdySessionSpdy3Test; + friend class SpdySessionTest; // Allow tests to access our innards for testing purposes. - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy2Test, ClientPing); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy2Test, FailedPing); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy2Test, GetActivePushStream); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy2Test, DeleteExpiredPushStreams); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy2Test, ProtocolNegotiation); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy2Test, ClearSettings); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, ClientPing); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, FailedPing); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, GetActivePushStream); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, DeleteExpiredPushStreams); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, ClearSettings); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, ProtocolNegotiation); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, ProtocolNegotiation31); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, ProtocolNegotiation4); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, AdjustRecvWindowSize31); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, AdjustSendWindowSize31); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, - SessionFlowControlInactiveStream31); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, - SessionFlowControlNoReceiveLeaks31); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, - SessionFlowControlNoSendLeaks31); - FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, ClientPing); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, FailedPing); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GetActivePushStream); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, DeleteExpiredPushStreams); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, ProtocolNegotiation); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, ClearSettings); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, AdjustRecvWindowSize); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, AdjustSendWindowSize); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlInactiveStream); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoReceiveLeaks); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoSendLeaks); + FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlEndToEnd); typedef std::deque<SpdyStreamRequest*> PendingStreamRequestQueue; typedef std::set<SpdyStreamRequest*> PendingStreamRequestCompletionSet; diff --git a/net/spdy/spdy_session_spdy2_unittest.cc b/net/spdy/spdy_session_spdy2_unittest.cc deleted file mode 100644 index aad6da4..0000000 --- a/net/spdy/spdy_session_spdy2_unittest.cc +++ /dev/null @@ -1,2498 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/spdy/spdy_session.h" - -#include "base/memory/scoped_ptr.h" -#include "base/run_loop.h" -#include "net/base/io_buffer.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_log_unittest.h" -#include "net/base/request_priority.h" -#include "net/base/test_data_directory.h" -#include "net/base/test_data_stream.h" -#include "net/dns/host_cache.h" -#include "net/socket/client_socket_pool_manager.h" -#include "net/socket/next_proto.h" -#include "net/spdy/spdy_session_pool.h" -#include "net/spdy/spdy_session_test_util.h" -#include "net/spdy/spdy_stream.h" -#include "net/spdy/spdy_stream_test_util.h" -#include "net/spdy/spdy_test_util_common.h" -#include "net/spdy/spdy_test_util_spdy2.h" -#include "net/spdy/spdy_test_utils.h" -#include "net/test/cert_test_util.h" -#include "testing/platform_test.h" - -using namespace net::test_spdy2; - -namespace net { - -namespace { - -static const char kTestUrl[] = "http://www.example.org/"; -static const char kTestHost[] = "www.example.org"; -static const int kTestPort = 80; - -static int g_delta_seconds = 0; -base::TimeTicks TheNearFuture() { - return base::TimeTicks::Now() + base::TimeDelta::FromSeconds(g_delta_seconds); -} - -} // namespace - -class SpdySessionSpdy2Test : public PlatformTest { - protected: - SpdySessionSpdy2Test() - : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL)), - old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( - HttpNetworkSession::NORMAL_SOCKET_POOL)), - spdy_util_(kProtoSPDY2), - session_deps_(kProtoSPDY2), - spdy_session_pool_(NULL), - test_url_(kTestUrl), - test_host_port_pair_(kTestHost, kTestPort), - key_(test_host_port_pair_, ProxyServer::Direct(), - kPrivacyModeDisabled) { - } - - virtual ~SpdySessionSpdy2Test() { - // Important to restore the per-pool limit first, since the pool limit must - // always be greater than group limit, and the tests reduce both limits. - ClientSocketPoolManager::set_max_sockets_per_pool( - HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_); - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_); - } - - virtual void SetUp() OVERRIDE { - g_delta_seconds = 0; - } - - void CreateDeterministicNetworkSession() { - http_session_ = - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); - spdy_session_pool_ = http_session_->spdy_session_pool(); - } - - void CreateNetworkSession() { - http_session_ = - SpdySessionDependencies::SpdyCreateSession(&session_deps_); - spdy_session_pool_ = http_session_->spdy_session_pool(); - } - - scoped_refptr<SpdySession> GetSession(const SpdySessionKey& key) { - EXPECT_FALSE(spdy_session_pool_->HasSession(key)); - scoped_refptr<SpdySession> session = - spdy_session_pool_->Get(key, BoundNetLog()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key)); - return session; - } - - // Creates an initialized session to |key_|. - scoped_refptr<SpdySession> CreateInitializedSession() { - scoped_refptr<SpdySession> session = GetSession(key_); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_)); - return session; - } - - net::Error InitializeSession(HttpNetworkSession* http_session, - SpdySession* session, - const HostPortPair& host_port_pair) { - transport_params_ = new TransportSocketParams( - host_port_pair, MEDIUM, false, false, OnHostResolutionCallback()); - - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), - transport_params_, MEDIUM, - CompletionCallback(), - http_session->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - return session->InitializeWithSocket(connection.release(), false, OK); - } - - // Original socket limits. Some tests set these. Safest to always restore - // them once each test has been run. - int old_max_group_sockets_; - int old_max_pool_sockets_; - - SpdyTestUtil spdy_util_; - scoped_refptr<TransportSocketParams> transport_params_; - SpdySessionDependencies session_deps_; - scoped_refptr<HttpNetworkSession> http_session_; - SpdySessionPool* spdy_session_pool_; - GURL test_url_; - HostPortPair test_host_port_pair_; - SpdySessionKey key_; -}; - -TEST_F(SpdySessionSpdy2Test, GoAway) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); - MockRead reads[] = { - CreateMockRead(*goaway, 2), - MockRead(ASYNC, 0, 3) // EOF - }; - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); - scoped_ptr<SpdyFrame> req2( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 0), - CreateMockWrite(*req2, 1), - }; - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - EXPECT_EQ(2, session->GetProtocolVersion()); - - GURL url("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url, MEDIUM, BoundNetLog()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url, MEDIUM, BoundNetLog()); - test::StreamDelegateDoNothing delegate2(spdy_stream2); - spdy_stream2->SetDelegate(&delegate2); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url.scheme(); - (*headers)["host"] = url.host(); - (*headers)["url"] = url.path(); - (*headers)["version"] = "HTTP/1.1"; - scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock); - *headers2 = *headers; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream2->HasUrl()); - data.RunFor(2); - - EXPECT_EQ(1u, spdy_stream1->stream_id()); - EXPECT_EQ(3u, spdy_stream2->stream_id()); - - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); - - // Read and process the GOAWAY frame. - data.RunFor(1); - - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); - - EXPECT_TRUE(session->IsStreamActive(1)); - EXPECT_FALSE(session->IsStreamActive(3)); - - scoped_refptr<SpdySession> session2 = GetSession(key_); - - spdy_stream1->Close(); - EXPECT_EQ(NULL, spdy_stream1.get()); - - // Delete the first session. - session = NULL; - - // Delete the second session. - spdy_session_pool_->Remove(session2); - session2 = NULL; - EXPECT_EQ(NULL, spdy_stream2.get()); -} - -TEST_F(SpdySessionSpdy2Test, ClientPing) { - session_deps_.enable_ping = true; - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1)); - MockRead reads[] = { - CreateMockRead(*read_ping), - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1)); - MockWrite writes[] = { - CreateMockWrite(*write_ping), - }; - StaticSocketDataProvider data( - reads, arraysize(reads), writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); - spdy_stream1->SetDelegate(&delegate); - - base::TimeTicks before_ping_time = base::TimeTicks::Now(); - - session->set_connection_at_risk_of_loss_time( - base::TimeDelta::FromSeconds(-1)); - session->set_hung_interval(base::TimeDelta::FromMilliseconds(50)); - - session->SendPrefacePingIfNoneInFlight(); - - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); - - session->CheckPingStatus(before_ping_time); - - EXPECT_EQ(0, session->pings_in_flight()); - EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1)); - EXPECT_FALSE(session->check_ping_status_pending()); - EXPECT_GE(session->last_activity_time(), before_ping_time); - - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); - - // Delete the first session. - session = NULL; -} - -TEST_F(SpdySessionSpdy2Test, ServerPing) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2)); - MockRead reads[] = { - CreateMockRead(*read_ping), - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2)); - MockWrite writes[] = { - CreateMockWrite(*write_ping), - }; - StaticSocketDataProvider data( - reads, arraysize(reads), writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); - spdy_stream1->SetDelegate(&delegate); - - // Flush the SpdySession::OnReadComplete() task. - base::MessageLoop::current()->RunUntilIdle(); - - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); - - // Delete the session. - session = NULL; - EXPECT_EQ(NULL, spdy_stream1.get()); -} - -TEST_F(SpdySessionSpdy2Test, DeleteExpiredPushStreams) { - session_deps_.host_resolver->set_synchronous_mode(true); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - session_deps_.time_func = TheNearFuture; - - CreateNetworkSession(); - - scoped_refptr<SpdySession> session = GetSession(key_); - - // Give the session a SPDY2 framer. - session->buffered_spdy_framer_.reset(new BufferedSpdyFramer(SPDY2, false)); - - // Create the associated stream and add to active streams. - scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock); - (*request_headers)["scheme"] = "http"; - (*request_headers)["host"] = "www.google.com"; - (*request_headers)["url"] = "/"; - - scoped_ptr<SpdyStream> stream(new SpdyStream(SPDY_REQUEST_RESPONSE_STREAM, - session.get(), - std::string(), - DEFAULT_PRIORITY, - kSpdyStreamInitialWindowSize, - kSpdyStreamInitialWindowSize, - session->net_log_)); - stream->SendRequestHeaders(request_headers.Pass(), NO_MORE_DATA_TO_SEND); - SpdyStream* stream_ptr = stream.get(); - session->InsertCreatedStream(stream.Pass()); - stream = session->ActivateCreatedStream(stream_ptr); - session->InsertActivatedStream(stream.Pass()); - - SpdyHeaderBlock headers; - headers["url"] = "http://www.google.com/a.dat"; - session->OnSynStream(2, 1, 0, 0, true, false, headers); - - // Verify that there is one unclaimed push stream. - EXPECT_EQ(1u, session->num_unclaimed_pushed_streams()); - SpdySession::PushedStreamMap::iterator iter = - session->unclaimed_pushed_streams_.find("http://www.google.com/a.dat"); - EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter); - - // Shift time. - g_delta_seconds = 301; - - headers["url"] = "http://www.google.com/b.dat"; - session->OnSynStream(4, 1, 0, 0, true, false, headers); - - // Verify that the second pushed stream evicted the first pushed stream. - EXPECT_EQ(1u, session->num_unclaimed_pushed_streams()); - iter = session->unclaimed_pushed_streams_.find("http://www.google.com/b.dat"); - EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter); - - // Delete the session. - session = NULL; -} - -TEST_F(SpdySessionSpdy2Test, FailedPing) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1)); - MockRead reads[] = { - CreateMockRead(*read_ping), - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1)); - MockWrite writes[] = { - CreateMockWrite(*write_ping), - }; - StaticSocketDataProvider data( - reads, arraysize(reads), writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); - spdy_stream1->SetDelegate(&delegate); - - session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0)); - session->set_hung_interval(base::TimeDelta::FromSeconds(0)); - - // Send a PING frame. - session->WritePingFrame(1); - EXPECT_LT(0, session->pings_in_flight()); - EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1)); - EXPECT_TRUE(session->check_ping_status_pending()); - - // Assert session is not closed. - EXPECT_FALSE(session->IsClosed()); - EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); - - // We set last time we have received any data in 1 sec less than now. - // CheckPingStatus will trigger timeout because hung interval is zero. - base::TimeTicks now = base::TimeTicks::Now(); - session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1); - session->CheckPingStatus(now); - - EXPECT_TRUE(session->IsClosed()); - EXPECT_EQ(0u, session->num_active_streams()); - EXPECT_EQ(0u, session->num_unclaimed_pushed_streams()); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); - - // Delete the first session. - session = NULL; - EXPECT_EQ(NULL, spdy_stream1.get()); -} - -TEST_F(SpdySessionSpdy2Test, CloseIdleSessions) { - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(ASYNC, 0, 0) // EOF - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - - // Set up session 1 - const std::string kTestHost1("http://www.a.com"); - HostPortPair test_host_port_pair1(kTestHost1, 80); - SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session1.get(), test_host_port_pair1)); - GURL url1(kTestHost1); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session1, url1, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - - // Set up session 2 - session_deps_.socket_factory->AddSocketDataProvider(&data); - const std::string kTestHost2("http://www.b.com"); - HostPortPair test_host_port_pair2(kTestHost2, 80); - SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session2 = GetSession(key2); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session2.get(), test_host_port_pair2)); - GURL url2(kTestHost2); - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session2, url2, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream2.get() != NULL); - - // Set up session 3 - session_deps_.socket_factory->AddSocketDataProvider(&data); - const std::string kTestHost3("http://www.c.com"); - HostPortPair test_host_port_pair3(kTestHost3, 80); - SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session3 = GetSession(key3); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session3.get(), test_host_port_pair3)); - GURL url3(kTestHost3); - base::WeakPtr<SpdyStream> spdy_stream3 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session3, url3, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream3.get() != NULL); - - // All sessions are active and not closed - EXPECT_TRUE(session1->is_active()); - EXPECT_FALSE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - EXPECT_TRUE(session3->is_active()); - EXPECT_FALSE(session3->IsClosed()); - - // Should not do anything, all are active - spdy_session_pool_->CloseIdleSessions(); - EXPECT_TRUE(session1->is_active()); - EXPECT_FALSE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - EXPECT_TRUE(session3->is_active()); - EXPECT_FALSE(session3->IsClosed()); - - // Make sessions 1 and 3 inactive, but keep them open. - // Session 2 still open and active - session1->CloseCreatedStream(spdy_stream1, OK); - EXPECT_EQ(NULL, spdy_stream1.get()); - session3->CloseCreatedStream(spdy_stream3, OK); - EXPECT_EQ(NULL, spdy_stream3.get()); - EXPECT_FALSE(session1->is_active()); - EXPECT_FALSE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - EXPECT_FALSE(session3->is_active()); - EXPECT_FALSE(session3->IsClosed()); - - // Should close session 1 and 3, 2 should be left open - spdy_session_pool_->CloseIdleSessions(); - EXPECT_FALSE(session1->is_active()); - EXPECT_TRUE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - EXPECT_FALSE(session3->is_active()); - EXPECT_TRUE(session3->IsClosed()); - - // Should not do anything - spdy_session_pool_->CloseIdleSessions(); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - - // Make 2 not active - session2->CloseCreatedStream(spdy_stream2, OK); - EXPECT_EQ(NULL, spdy_stream2.get()); - EXPECT_FALSE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - - // This should close session 2 - spdy_session_pool_->CloseIdleSessions(); - EXPECT_FALSE(session2->is_active()); - EXPECT_TRUE(session2->IsClosed()); -} - -// 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 -TEST_F(SpdySessionSpdy2Test, OnSettings) { - session_deps_.host_resolver->set_synchronous_mode(true); - - SettingsMap new_settings; - const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; - const uint32 max_concurrent_streams = 2; - new_settings[kSpdySettingsIds1] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); - - // Set up the socket so we read a SETTINGS frame that raises max concurrent - // streams to 2. - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> settings_frame( - spdy_util_.ConstructSpdySettings(new_settings)); - MockRead reads[] = { - CreateMockRead(*settings_frame), - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - // Initialize the SpdySetting with 1 max concurrent streams. - spdy_session_pool_->http_server_properties()->SetSpdySetting( - test_host_port_pair_, - kSpdySettingsIds1, - SETTINGS_FLAG_PLEASE_PERSIST, - 1); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - // 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); - - StreamReleaserCallback stream_releaser; - SpdyStreamRequest request; - ASSERT_EQ(ERR_IO_PENDING, - request.StartRequest( - SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, - BoundNetLog(), - stream_releaser.MakeCallback(&request))); - - EXPECT_EQ(OK, stream_releaser.WaitForResult()); -} - -// 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. -TEST_F(SpdySessionSpdy2Test, ClearSettings) { - session_deps_.host_resolver->set_synchronous_mode(true); - - SettingsMap new_settings; - const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; - const uint32 max_concurrent_streams = 2; - new_settings[kSpdySettingsIds1] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); - - // Set up the socket so we read a SETTINGS frame that raises max concurrent - // streams to 2 and clears previously persisted data. - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> settings_frame( - spdy_util_.ConstructSpdySettings(new_settings)); - uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; - test::SetFrameFlags(settings_frame.get(), flags, SPDY3); - MockRead reads[] = { - CreateMockRead(*settings_frame), - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - // Initialize the SpdySetting with 1 max concurrent streams. - spdy_session_pool_->http_server_properties()->SetSpdySetting( - test_host_port_pair_, - kSpdySettingsIds1, - SETTINGS_FLAG_PLEASE_PERSIST, - 1); - - EXPECT_EQ(1u, spdy_session_pool_->http_server_properties()->GetSpdySettings( - test_host_port_pair_).size()); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - // 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); - - StreamReleaserCallback stream_releaser; - SpdyStreamRequest request; - ASSERT_EQ(ERR_IO_PENDING, - request.StartRequest( - SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, - BoundNetLog(), - stream_releaser.MakeCallback(&request))); - - 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()); - - // Make sure session's max_concurrent_streams is 2. - EXPECT_EQ(2u, session->max_concurrent_streams()); - - 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 -TEST_F(SpdySessionSpdy2Test, CancelPendingCreateStream) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - MockConnect connect_data(SYNCHRONOUS, OK); - - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - 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); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - // 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); - - // Use scoped_ptr to let us invalidate the memory when we want to, to trigger - // a valgrind error if the callback is invoked when it's not supposed to be. - scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback); - - SpdyStreamRequest request; - ASSERT_EQ(ERR_IO_PENDING, - request.StartRequest( - SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, - BoundNetLog(), - callback->callback())); - - // Release the first one, this will allow the second to be created. - spdy_stream1->Cancel(); - EXPECT_EQ(NULL, spdy_stream1.get()); - - request.CancelRequest(); - callback.reset(); - - // Should not crash when running the pending callback. - base::MessageLoop::current()->RunUntilIdle(); -} - -TEST_F(SpdySessionSpdy2Test, SendInitialSettingsOnNewSession) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - - SettingsMap settings; - const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; - settings[kSpdySettingsIds1] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> settings_frame( - spdy_util_.ConstructSpdySettings(settings)); - MockWrite writes[] = { - CreateMockWrite(*settings_frame), - }; - - StaticSocketDataProvider data( - reads, arraysize(reads), writes, arraysize(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); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - base::MessageLoop::current()->RunUntilIdle(); - EXPECT_TRUE(data.at_write_eof()); -} - -TEST_F(SpdySessionSpdy2Test, SendSettingsOnNewSession) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - - // 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), - }; - - StaticSocketDataProvider data( - reads, arraysize(reads), writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - spdy_session_pool_->http_server_properties()->SetSpdySetting( - test_host_port_pair_, - kSpdySettingsIds1, - SETTINGS_FLAG_PLEASE_PERSIST, - kBogusSettingValue); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - base::MessageLoop::current()->RunUntilIdle(); - EXPECT_TRUE(data.at_write_eof()); -} - -namespace { - -// Specifies the style for closing the connection. -enum SpdyPoolCloseSessionsType { - SPDY_POOL_CLOSE_SESSIONS_MANUALLY, - SPDY_POOL_CLOSE_CURRENT_SESSIONS, - SPDY_POOL_CLOSE_IDLE_SESSIONS, -}; - -// Initialize the SpdySession with socket. -void IPPoolingInitializedSession( - const std::string& group_name, - const scoped_refptr<TransportSocketParams>& transport_params, - HttpNetworkSession* http_session, - SpdySession* session) { - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(group_name, - transport_params, MEDIUM, CompletionCallback(), - http_session->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); -} - -// This test has three variants, one for each style of closing the connection. -// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY, -// the sessions are closed manually, calling SpdySessionPool::Remove() directly. -// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS, -// sessions are closed with SpdySessionPool::CloseCurrentSessions(). -// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS, -// sessions are closed with SpdySessionPool::CloseIdleSessions(). -void IPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type) { - const int kTestPort = 80; - struct TestHosts { - std::string url; - std::string name; - std::string iplist; - SpdySessionKey key; - AddressList addresses; - } test_hosts[] = { - { "http:://www.foo.com", - "www.foo.com", - "192.0.2.33,192.168.0.1,192.168.0.5" - }, - { "http://js.foo.com", - "js.foo.com", - "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33" - }, - { "http://images.foo.com", - "images.foo.com", - "192.168.0.4,192.168.0.3" - }, - }; - - SpdySessionDependencies session_deps(kProtoSPDY2); - session_deps.host_resolver->set_synchronous_mode(true); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { - session_deps.host_resolver->rules()->AddIPLiteralRule( - test_hosts[i].name, test_hosts[i].iplist, std::string()); - - // This test requires that the HostResolver cache be populated. Normal - // code would have done this already, but we do it manually. - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - session_deps.host_resolver->Resolve( - info, &test_hosts[i].addresses, CompletionCallback(), NULL, - BoundNetLog()); - - // Setup a SpdySessionKey - test_hosts[i].key = SpdySessionKey( - HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), - kPrivacyModeDisabled); - } - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); - - scoped_refptr<HttpNetworkSession> http_session( - SpdySessionDependencies::SpdyCreateSession(&session_deps)); - - // Setup the first session to the first host. - SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[0].key)); - scoped_refptr<SpdySession> session = - spdy_session_pool->Get(test_hosts[0].key, BoundNetLog()); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[0].key)); - - HostPortPair test_host_port_pair(test_hosts[0].name, kTestPort); - - // Initialize session for the first host. - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(test_host_port_pair, - MEDIUM, - false, - false, - OnHostResolutionCallback())); - IPPoolingInitializedSession(test_host_port_pair.ToString(), - transport_params, - http_session.get(), - session.get()); - - // TODO(rtenneti): MockClientSocket::GetPeerAddress return's 0 as the port - // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. - SpdySessionPoolPeer pool_peer(spdy_session_pool); - pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key); - - // Flush the SpdySession::OnReadComplete() task. - base::MessageLoop::current()->RunUntilIdle(); - - // The third host has no overlap with the first, so it can't pool IPs. - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); - - // The second host overlaps with the first, and should IP pool. - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - - // Verify that the second host, through a proxy, won't share the IP. - SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(), - ProxyServer::FromPacString("HTTP http://proxy.foo.com/"), - kPrivacyModeDisabled); - EXPECT_FALSE(spdy_session_pool->HasSession(proxy_key)); - - // Overlap between 2 and 3 does is not transitive to 1. - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); - - // Create a new session to host 2. - scoped_refptr<SpdySession> session2 = - spdy_session_pool->Get(test_hosts[2].key, BoundNetLog()); - - // Verify that we have sessions for everything. - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[0].key)); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[2].key)); - - // Initialize session for host 2. - session_deps.socket_factory->AddSocketDataProvider(&data); - IPPoolingInitializedSession(test_hosts[2].key.host_port_pair().ToString(), - transport_params, - http_session.get(), - session2.get()); - - // Grab the session to host 1 and verify that it is the same session - // we got with host 0, and that is a different than host 2's session. - scoped_refptr<SpdySession> session1 = - spdy_session_pool->Get(test_hosts[1].key, BoundNetLog()); - EXPECT_EQ(session.get(), session1.get()); - EXPECT_NE(session2.get(), session1.get()); - - // Initialize session for host 1. - session_deps.socket_factory->AddSocketDataProvider(&data); - IPPoolingInitializedSession(test_hosts[2].key.host_port_pair().ToString(), - transport_params, - http_session.get(), - session2.get()); - - // Remove the aliases and observe that we still have a session for host1. - pool_peer.RemoveAliases(test_hosts[0].key); - pool_peer.RemoveAliases(test_hosts[1].key); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - - // Expire the host cache - session_deps.host_resolver->GetHostCache()->clear(); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - - // Cleanup the sessions. - switch (close_sessions_type) { - case SPDY_POOL_CLOSE_SESSIONS_MANUALLY: - spdy_session_pool->Remove(session); - session = NULL; - spdy_session_pool->Remove(session2); - session2 = NULL; - break; - case SPDY_POOL_CLOSE_CURRENT_SESSIONS: - spdy_session_pool->CloseCurrentSessions(net::ERR_ABORTED); - break; - case SPDY_POOL_CLOSE_IDLE_SESSIONS: - GURL url(test_hosts[0].url); - base::WeakPtr<SpdyStream> spdy_stream = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, BoundNetLog()); - GURL url1(test_hosts[1].url); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session1, url1, MEDIUM, BoundNetLog()); - GURL url2(test_hosts[2].url); - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously( - SPDY_BIDIRECTIONAL_STREAM, session2, url2, MEDIUM, BoundNetLog()); - - // Close streams to make spdy_session and spdy_session1 inactive. - session->CloseCreatedStream(spdy_stream, OK); - EXPECT_EQ(NULL, spdy_stream.get()); - session1->CloseCreatedStream(spdy_stream1, OK); - EXPECT_EQ(NULL, spdy_stream1.get()); - - // Check spdy_session and spdy_session1 are not closed. - EXPECT_FALSE(session->is_active()); - EXPECT_FALSE(session->IsClosed()); - EXPECT_FALSE(session1->is_active()); - EXPECT_FALSE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - - // Test that calling CloseIdleSessions, does not cause a crash. - // http://crbug.com/181400 - spdy_session_pool->CloseIdleSessions(); - - // Verify spdy_session and spdy_session1 are closed. - EXPECT_FALSE(session->is_active()); - EXPECT_TRUE(session->IsClosed()); - EXPECT_FALSE(session1->is_active()); - EXPECT_TRUE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - - spdy_stream2->Cancel(); - EXPECT_EQ(NULL, spdy_stream2.get()); - spdy_session_pool->Remove(session2); - session2 = NULL; - break; - } - - // Verify that the map is all cleaned up. - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[0].key)); - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[1].key)); - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); -} - -} // namespace - -TEST_F(SpdySessionSpdy2Test, IPPooling) { - IPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY); -} - -TEST_F(SpdySessionSpdy2Test, IPPoolingCloseCurrentSessions) { - IPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS); -} - -TEST_F(SpdySessionSpdy2Test, IPPoolingCloseIdleSessions) { - IPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS); -} - -TEST_F(SpdySessionSpdy2Test, ClearSettingsStorageOnIPAddressChanged) { - CreateNetworkSession(); - - HttpServerProperties* test_http_server_properties = - spdy_session_pool_->http_server_properties(); - SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2); - test_http_server_properties->SetSpdySetting( - test_host_port_pair_, - SETTINGS_MAX_CONCURRENT_STREAMS, - SETTINGS_FLAG_PLEASE_PERSIST, - 2); - EXPECT_NE(0u, test_http_server_properties->GetSpdySettings( - test_host_port_pair_).size()); - spdy_session_pool_->OnIPAddressChanged(); - EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings( - test_host_port_pair_).size()); -} - -TEST_F(SpdySessionSpdy2Test, CloseSessionOnError) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); - MockRead reads[] = { - CreateMockRead(*goaway), - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - CapturingBoundNetLog log; - scoped_refptr<SpdySession> session = - spdy_session_pool_->Get(key_, log.bound()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); - - InitializeSession(http_session_.get(), session.get(), test_host_port_pair_); - - // Flush the SpdySession::OnReadComplete() task. - base::MessageLoop::current()->RunUntilIdle(); - - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); - - // Check that the NetLog was filled reasonably. - net::CapturingNetLog::CapturedEntryList entries; - log.GetEntries(&entries); - EXPECT_LT(0u, entries.size()); - - // Check that we logged SPDY_SESSION_CLOSE correctly. - int pos = net::ExpectLogContainsSomewhere( - entries, 0, - net::NetLog::TYPE_SPDY_SESSION_CLOSE, - net::NetLog::PHASE_NONE); - - CapturingNetLog::CapturedEntry entry = entries[pos]; - int error_code = 0; - ASSERT_TRUE(entry.GetNetErrorCode(&error_code)); - EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code); -} - -TEST_F(SpdySessionSpdy2Test, OutOfOrderSynStreams) { - // Construct the request. - MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true)); - scoped_ptr<SpdyFrame> req2( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 2), - CreateMockWrite(*req2, 1), - }; - - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, true)); - MockRead reads[] = { - CreateMockRead(*resp1, 3), - CreateMockRead(*body1, 4), - CreateMockRead(*resp2, 5), - CreateMockRead(*body2, 6), - MockRead(ASYNC, 0, 7) // EOF - }; - - session_deps_.host_resolver->set_synchronous_mode(true); - - StaticSocketDataProvider data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url("http://www.google.com"); - - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url, LOWEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url, HIGHEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream2.get() != NULL); - EXPECT_EQ(0u, spdy_stream2->stream_id()); - test::StreamDelegateDoNothing delegate2(spdy_stream2); - spdy_stream2->SetDelegate(&delegate2); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url.scheme(); - (*headers)["host"] = url.host(); - (*headers)["url"] = url.path(); - (*headers)["version"] = "HTTP/1.1"; - scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock); - *headers2 = *headers; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream2->HasUrl()); - - base::MessageLoop::current()->RunUntilIdle(); - - EXPECT_EQ(NULL, spdy_stream1.get()); - EXPECT_EQ(NULL, spdy_stream2.get()); - EXPECT_EQ(3u, delegate1.stream_id()); - EXPECT_EQ(1u, delegate2.stream_id()); -} - -TEST_F(SpdySessionSpdy2Test, CancelStream) { - MockConnect connect_data(SYNCHRONOUS, OK); - // Request 1, at HIGHEST priority, will be cancelled before it writes data. - // Request 2, at LOWEST priority, will be a full request and will be id 1. - scoped_ptr<SpdyFrame> req2( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); - MockWrite writes[] = { - CreateMockWrite(*req2, 0), - }; - - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(1, true)); - MockRead reads[] = { - CreateMockRead(*resp2, 1), - CreateMockRead(*body2, 2), - MockRead(ASYNC, 0, 3) // EOF - }; - - session_deps_.host_resolver->set_synchronous_mode(true); - - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url1, HIGHEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - GURL url2("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url2, LOWEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream2.get() != NULL); - EXPECT_EQ(0u, spdy_stream2->stream_id()); - test::StreamDelegateDoNothing delegate2(spdy_stream2); - spdy_stream2->SetDelegate(&delegate2); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock); - *headers2 = *headers; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream2->HasUrl()); - - EXPECT_EQ(0u, spdy_stream1->stream_id()); - - spdy_stream1->Cancel(); - EXPECT_EQ(NULL, spdy_stream1.get()); - - EXPECT_EQ(0u, delegate1.stream_id()); - - data.RunFor(1); - - EXPECT_EQ(0u, delegate1.stream_id()); - EXPECT_EQ(1u, delegate2.stream_id()); - - spdy_stream2->Cancel(); - EXPECT_EQ(NULL, spdy_stream2.get()); -} - -TEST_F(SpdySessionSpdy2Test, CloseSessionWithTwoCreatedStreams) { - session_deps_.host_resolver->set_synchronous_mode(true); - - // Test that if a sesion is closed with two created streams pending, - // it does not crash. http://crbug.com/139518 - MockConnect connect_data(SYNCHRONOUS, OK); - - // No actual data will be sent. - MockWrite writes[] = { - MockWrite(ASYNC, 0, 1) // EOF - }; - - MockRead reads[] = { - MockRead(ASYNC, 0, 0) // EOF - }; - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session, url1, HIGHEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - - GURL url2("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session, url2, LOWEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream2.get() != NULL); - EXPECT_EQ(0u, spdy_stream2->stream_id()); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock); - *headers2 = *headers; - - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - test::StreamDelegateDoNothing delegate2(spdy_stream2); - spdy_stream2->SetDelegate(&delegate2); - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream2->HasUrl()); - - // Ensure that the streams have not yet been activated and assigned an id. - EXPECT_EQ(0u, spdy_stream1->stream_id()); - EXPECT_EQ(0u, spdy_stream2->stream_id()); - - // Ensure we don't crash while closing the session. - session->CloseSessionOnError(ERR_ABORTED, true, std::string()); - - EXPECT_EQ(NULL, spdy_stream1.get()); - EXPECT_EQ(NULL, spdy_stream2.get()); - - EXPECT_TRUE(delegate1.StreamIsClosed()); - EXPECT_TRUE(delegate2.StreamIsClosed()); -} - -TEST_F(SpdySessionSpdy2Test, VerifyDomainAuthentication) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - - // No actual data will be sent. - MockWrite writes[] = { - MockWrite(ASYNC, 0, 1) // EOF - }; - - MockRead reads[] = { - MockRead(ASYNC, 0, 0) // EOF - }; - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - // Load a cert that is valid for: - // www.example.org - // mail.example.org - // www.example.com - base::FilePath certs_dir = GetTestCertsDirectory(); - scoped_refptr<X509Certificate> test_cert( - ImportCertFromFile(certs_dir, "spdy_pooling.pem")); - ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - ssl.cert = test_cert; - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = GetSession(key_); - - SSLConfig ssl_config; - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(test_host_port_pair_, - MEDIUM, - false, - false, - OnHostResolutionCallback())); - scoped_refptr<SOCKSSocketParams> socks_params; - scoped_refptr<HttpProxySocketParams> http_proxy_params; - scoped_refptr<SSLSocketParams> ssl_params( - new SSLSocketParams(transport_params, - socks_params, - http_proxy_params, - ProxyServer::SCHEME_DIRECT, - test_host_port_pair_, - ssl_config, - 0, - false, - false)); - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(test_host_port_pair_.ToString(), - ssl_params, MEDIUM, CompletionCallback(), - http_session_->GetSSLSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); - EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); - EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); - EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com")); - EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); -} - -TEST_F(SpdySessionSpdy2Test, ConnectionPooledWithTlsChannelId) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - - // No actual data will be sent. - MockWrite writes[] = { - MockWrite(ASYNC, 0, 1) // EOF - }; - - MockRead reads[] = { - MockRead(ASYNC, 0, 0) // EOF - }; - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - // Load a cert that is valid for: - // www.example.org - // mail.example.org - // www.example.com - base::FilePath certs_dir = GetTestCertsDirectory(); - scoped_refptr<X509Certificate> test_cert( - ImportCertFromFile(certs_dir, "spdy_pooling.pem")); - ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - ssl.channel_id_sent = true; - ssl.cert = test_cert; - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = GetSession(key_); - - SSLConfig ssl_config; - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(test_host_port_pair_, - MEDIUM, - false, - false, - OnHostResolutionCallback())); - scoped_refptr<SOCKSSocketParams> socks_params; - scoped_refptr<HttpProxySocketParams> http_proxy_params; - scoped_refptr<SSLSocketParams> ssl_params( - new SSLSocketParams(transport_params, - socks_params, - http_proxy_params, - ProxyServer::SCHEME_DIRECT, - test_host_port_pair_, - ssl_config, - 0, - false, - false)); - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(test_host_port_pair_.ToString(), - ssl_params, MEDIUM, CompletionCallback(), - http_session_->GetSSLSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); - EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); - EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); - EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com")); - EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); -} - -TEST_F(SpdySessionSpdy2Test, CloseTwoStalledCreateStream) { - // TODO(rtenneti): Define a helper class/methods and move the common code in - // this file. - MockConnect connect_data(SYNCHRONOUS, OK); - - SettingsMap new_settings; - const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; - const uint32 max_concurrent_streams = 1; - new_settings[kSpdySettingsIds1] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); - - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); - scoped_ptr<SpdyFrame> req2( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); - scoped_ptr<SpdyFrame> req3( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 1), - CreateMockWrite(*req2, 4), - CreateMockWrite(*req3, 7), - }; - - // Set up the socket so we read a SETTINGS frame that sets max concurrent - // streams to 1. - scoped_ptr<SpdyFrame> settings_frame( - spdy_util_.ConstructSpdySettings(new_settings)); - - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); - - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, true)); - - scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5)); - scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(5, true)); - - MockRead reads[] = { - CreateMockRead(*settings_frame), - CreateMockRead(*resp1, 2), - CreateMockRead(*body1, 3), - CreateMockRead(*resp2, 5), - CreateMockRead(*body2, 6), - CreateMockRead(*resp3, 8), - CreateMockRead(*body3, 9), - MockRead(ASYNC, 0, 10) // EOF - }; - - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - // Read the settings frame. - data.RunFor(1); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url1, LOWEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - TestCompletionCallback callback2; - GURL url2("http://www.google.com"); - SpdyStreamRequest request2; - ASSERT_EQ(ERR_IO_PENDING, - request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, - session, url2, LOWEST, BoundNetLog(), - callback2.callback())); - - TestCompletionCallback callback3; - GURL url3("http://www.google.com"); - SpdyStreamRequest request3; - ASSERT_EQ(ERR_IO_PENDING, - request3.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, - session, url3, LOWEST, BoundNetLog(), - callback3.callback())); - - EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); - EXPECT_EQ(2u, session->pending_create_stream_queues(LOWEST)); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock); - *headers2 = *headers; - scoped_ptr<SpdyHeaderBlock> headers3(new SpdyHeaderBlock); - *headers3 = *headers; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - - // Run until 1st stream is closed and 2nd one is opened. - 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_queues(LOWEST)); - - base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream(); - test::StreamDelegateDoNothing delegate2(stream2); - stream2->SetDelegate(&delegate2); - stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(stream2->HasUrl()); - - // Run until 2nd stream is 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->pending_create_stream_queues(LOWEST)); - - base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream(); - ASSERT_TRUE(stream3.get() != NULL); - test::StreamDelegateDoNothing delegate3(stream3); - stream3->SetDelegate(&delegate3); - stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(stream3->HasUrl()); - - EXPECT_EQ(0u, delegate3.stream_id()); - data.RunFor(4); - 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->pending_create_stream_queues(LOWEST)); -} - -TEST_F(SpdySessionSpdy2Test, CancelTwoStalledCreateStream) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - MockConnect connect_data(SYNCHRONOUS, OK); - - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - 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); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session, url1, LOWEST, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - - TestCompletionCallback callback2; - GURL url2("http://www.google.com"); - SpdyStreamRequest request2; - ASSERT_EQ(ERR_IO_PENDING, - request2.StartRequest(SPDY_BIDIRECTIONAL_STREAM, - session, url2, LOWEST, - BoundNetLog(), - callback2.callback())); - - TestCompletionCallback callback3; - GURL url3("http://www.google.com"); - SpdyStreamRequest request3; - ASSERT_EQ(ERR_IO_PENDING, - request3.StartRequest(SPDY_BIDIRECTIONAL_STREAM, - session, url3, LOWEST, - BoundNetLog(), - callback3.callback())); - - EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); - EXPECT_EQ(2u, session->pending_create_stream_queues(LOWEST)); - - // 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_queues(LOWEST)); - - // 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(0u, session->pending_create_stream_queues(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->pending_create_stream_queues(LOWEST)); -} - -TEST_F(SpdySessionSpdy2Test, NeedsCredentials) { - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - ssl.channel_id_sent = true; - ssl.protocol_negotiated = kProtoSPDY2; - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateNetworkSession(); - - const std::string kTestHost("www.foo.com"); - const int kTestPort = 80; - HostPortPair test_host_port_pair(kTestHost, kTestPort); - SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - - scoped_refptr<SpdySession> session = GetSession(key); - - SSLConfig ssl_config; - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(test_host_port_pair, - MEDIUM, - false, - false, - OnHostResolutionCallback())); - scoped_refptr<SOCKSSocketParams> socks_params; - scoped_refptr<HttpProxySocketParams> http_proxy_params; - scoped_refptr<SSLSocketParams> ssl_params( - new SSLSocketParams(transport_params, - socks_params, - http_proxy_params, - ProxyServer::SCHEME_DIRECT, - test_host_port_pair, - ssl_config, - 0, - false, - false)); - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(), - ssl_params, MEDIUM, CompletionCallback(), - http_session_->GetSSLSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); - - EXPECT_FALSE(session->NeedsCredentials()); - - // Flush the SpdySession::OnReadComplete() task. - base::MessageLoop::current()->RunUntilIdle(); - - spdy_session_pool_->Remove(session); -} - -// Test that SpdySession::DoRead reads data from the socket without yielding. -// This test makes 32k - 1 bytes of data available on the socket for reading. It -// then verifies that it has read all the available data without yielding. -TEST_F(SpdySessionSpdy2Test, ReadDataWithoutYielding) { - MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY2, false); - - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 0), - }; - - // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). - ASSERT_EQ(32 * 1024, kMaxReadBytes); - const int kPayloadSize = - kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize(); - TestDataStream test_stream; - scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); - char* payload_data = payload->data(); - test_stream.GetBytes(payload_data, kPayloadSize); - - scoped_ptr<SpdyFrame> partial_data_frame( - framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); - scoped_ptr<SpdyFrame> finish_data_frame( - framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); - - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - - // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k - // bytes. - MockRead reads[] = { - CreateMockRead(*resp1, 1), - CreateMockRead(*partial_data_frame, 2), - CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), - CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), - CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS), - MockRead(ASYNC, 0, 6) // EOF - }; - - // Create SpdySession and SpdyStream and send the request. - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.host_resolver->set_synchronous_mode(true); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url1, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - - // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task. - SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); - - // Run until 1st read. - EXPECT_EQ(0u, delegate1.stream_id()); - data.RunFor(2); - EXPECT_EQ(1u, delegate1.stream_id()); - EXPECT_EQ(0u, observer.executed_count()); - - // Read all the data and verify SpdySession::DoRead has not posted a task. - data.RunFor(4); - EXPECT_EQ(NULL, spdy_stream1.get()); - - // Verify task observer's executed_count is zero, which indicates DoRead read - // all the available data. - EXPECT_EQ(0u, observer.executed_count()); - EXPECT_TRUE(data.at_write_eof()); - EXPECT_TRUE(data.at_read_eof()); -} - -// Test that SpdySession::DoRead yields while reading the data. This test makes -// 32k + 1 bytes of data available on the socket for reading. It then verifies -// that DoRead has yielded even though there is data available for it to read -// (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads). -TEST_F(SpdySessionSpdy2Test, TestYieldingDuringReadData) { - MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY2, false); - - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 0), - }; - - // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). - ASSERT_EQ(32 * 1024, kMaxReadBytes); - const int kPayloadSize = - kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize(); - TestDataStream test_stream; - scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); - char* payload_data = payload->data(); - test_stream.GetBytes(payload_data, kPayloadSize); - - scoped_ptr<SpdyFrame> partial_data_frame( - framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); - scoped_ptr<SpdyFrame> finish_data_frame( - framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); - - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - - // Write 1 byte more than kMaxReadBytes to check that DoRead yields. - MockRead reads[] = { - CreateMockRead(*resp1, 1), - CreateMockRead(*partial_data_frame, 2), - CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), - CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), - CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS), - CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS), - MockRead(ASYNC, 0, 7) // EOF - }; - - // Create SpdySession and SpdyStream and send the request. - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.host_resolver->set_synchronous_mode(true); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url1, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - - // Set up the TaskObserver to verify SpdySession::DoRead posts a task. - SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); - - // Run until 1st read. - EXPECT_EQ(0u, delegate1.stream_id()); - data.RunFor(2); - EXPECT_EQ(1u, delegate1.stream_id()); - EXPECT_EQ(0u, observer.executed_count()); - - // Read all the data and verify SpdySession::DoRead has posted a task. - data.RunFor(6); - EXPECT_EQ(NULL, spdy_stream1.get()); - - // Verify task observer's executed_count is 1, which indicates DoRead has - // posted only one task and thus yielded though there is data available for it - // to read. - EXPECT_EQ(1u, observer.executed_count()); - EXPECT_TRUE(data.at_write_eof()); - EXPECT_TRUE(data.at_read_eof()); -} - -// Test that SpdySession::DoRead() tests interactions of yielding + async, -// by doing the following MockReads. -// -// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K -// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K. -// -// The above reads 26K synchronously. Since that is less that 32K, we will -// attempt to read again. However, that DoRead() will return ERR_IO_PENDING -// (because of async read), so DoRead() will yield. When we come back, DoRead() -// will read the results from the async read, and rest of the data -// synchronously. -TEST_F(SpdySessionSpdy2Test, TestYieldingDuringAsyncReadData) { - MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY2, false); - - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 0), - }; - - // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). - ASSERT_EQ(32 * 1024, kMaxReadBytes); - TestDataStream test_stream; - const int kEightKPayloadSize = - kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize(); - scoped_refptr<net::IOBuffer> eightk_payload( - new net::IOBuffer(kEightKPayloadSize)); - char* eightk_payload_data = eightk_payload->data(); - test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize); - - // Build buffer of 2k size. - TestDataStream test_stream2; - const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; - scoped_refptr<net::IOBuffer> twok_payload( - new net::IOBuffer(kTwoKPayloadSize)); - char* twok_payload_data = twok_payload->data(); - test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); - - scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( - 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); - scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( - 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); - scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( - 1, "h", 1, DATA_FLAG_FIN)); - - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - - MockRead reads[] = { - CreateMockRead(*resp1, 1), - CreateMockRead(*eightk_data_frame, 2), - CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), - CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), - CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), - CreateMockRead(*eightk_data_frame, 6, ASYNC), - CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), - CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), - CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), - CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), - CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), - MockRead(ASYNC, 0, 12) // EOF - }; - - // Create SpdySession and SpdyStream and send the request. - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.host_resolver->set_synchronous_mode(true); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url1, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - - // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks. - SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); - - // Run until 1st read. - EXPECT_EQ(0u, delegate1.stream_id()); - data.RunFor(2); - EXPECT_EQ(1u, delegate1.stream_id()); - EXPECT_EQ(0u, observer.executed_count()); - - // Read all the data and verify SpdySession::DoRead has posted a task. - data.RunFor(12); - EXPECT_EQ(NULL, spdy_stream1.get()); - - // Verify task observer's executed_count is 1, which indicates DoRead has - // posted only one task and thus yielded though there is data available for - // it to read. - EXPECT_EQ(1u, observer.executed_count()); - EXPECT_TRUE(data.at_write_eof()); - EXPECT_TRUE(data.at_read_eof()); -} - -// Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to -// <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because -// GoAway could delete the SpdySession from the SpdySessionPool and the last -// reference to SpdySession. -TEST_F(SpdySessionSpdy2Test, GoAwayWhileInDoLoop) { - MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY2, false); - - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 0), - }; - - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); - scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); - - MockRead reads[] = { - CreateMockRead(*resp1, 1), - CreateMockRead(*body1, 2), - CreateMockRead(*goaway, 3), - MockRead(ASYNC, 0, 4) // EOF - }; - - // Create SpdySession and SpdyStream and send the request. - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.host_resolver->set_synchronous_mode(true); - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); - - CreateDeterministicNetworkSession(); - - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - GURL url1("http://www.google.com"); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session, url1, MEDIUM, BoundNetLog()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - session = NULL; - ASSERT_TRUE(spdy_stream1.get() != NULL); - EXPECT_EQ(0u, spdy_stream1->stream_id()); - - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)["method"] = "GET"; - (*headers)["scheme"] = url1.scheme(); - (*headers)["host"] = url1.host(); - (*headers)["url"] = url1.path(); - (*headers)["version"] = "HTTP/1.1"; - - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - - // Run until 1st read. - EXPECT_EQ(0u, spdy_stream1->stream_id()); - data.RunFor(1); - EXPECT_EQ(1u, spdy_stream1->stream_id()); - - // Only references to SpdySession are held by DoLoop and - // SpdySessionPool. If DoLoop doesn't hold the reference, we get a - // crash if SpdySession is deleted from the SpdySessionPool. - - // Run until GoAway. - data.RunFor(4); - EXPECT_EQ(NULL, spdy_stream1.get()); - EXPECT_TRUE(data.at_write_eof()); - EXPECT_TRUE(data.at_read_eof()); -} - -// Within this framework, a SpdySession should be initialized with -// flow control disabled and with protocol version 2. -TEST_F(SpdySessionSpdy2Test, ProtocolNegotiation) { - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - - EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); - EXPECT_TRUE(session->buffered_spdy_framer_ == NULL); - EXPECT_EQ(0, session->session_send_window_size_); - EXPECT_EQ(0, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); - - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); - - EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); - EXPECT_EQ(SPDY2, session->buffered_spdy_framer_->protocol_version()); - EXPECT_EQ(0, session->session_send_window_size_); - EXPECT_EQ(0, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); -} - -// Tests the case of a non-SPDY request closing an idle SPDY session when no -// pointers to the idle session are currently held. -TEST_F(SpdySessionSpdy2Test, CloseOneIdleConnection) { - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - ClientSocketPoolManager::set_max_sockets_per_pool( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - - TransportClientSocketPool* pool = - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL); - - // Create an idle SPDY session. - SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); - EXPECT_FALSE(pool->IsStalled()); - // Release the pointer to the session so it can be closed. - session1 = NULL; - - // Trying to create a new connection should cause the pool to be stalled, and - // post a task asynchronously to try and close the session. - TestCompletionCallback callback2; - HostPortPair host_port2("2.com", 80); - scoped_refptr<TransportSocketParams> params2( - new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, - OnHostResolutionCallback())); - scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, - callback2.callback(), pool, BoundNetLog())); - EXPECT_TRUE(pool->IsStalled()); - - // The socket pool should close the connection asynchronously and establish a - // new connection. - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_FALSE(pool->IsStalled()); -} - -// Tests the case of a non-SPDY request closing an idle SPDY session when no -// pointers to the idle session are currently held, in the case the SPDY session -// has an alias. -TEST_F(SpdySessionSpdy2Test, CloseOneIdleConnectionWithAlias) { - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - ClientSocketPoolManager::set_max_sockets_per_pool( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - session_deps_.host_resolver->set_synchronous_mode(true); - session_deps_.host_resolver->rules()->AddIPLiteralRule( - "1.com", "192.168.0.2", std::string()); - session_deps_.host_resolver->rules()->AddIPLiteralRule( - "2.com", "192.168.0.2", std::string()); - // Not strictly needed. - session_deps_.host_resolver->rules()->AddIPLiteralRule( - "3.com", "192.168.0.3", std::string()); - - CreateNetworkSession(); - - TransportClientSocketPool* pool = - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL); - - // Create an idle SPDY session. - SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); - EXPECT_FALSE(pool->IsStalled()); - - // Set up an alias for the idle SPDY session, increasing its ref count to 2. - SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(), - kPrivacyModeDisabled); - SpdySessionPoolPeer pool_peer(spdy_session_pool_); - HostResolver::RequestInfo info(key2.host_port_pair()); - AddressList addresses; - // Pre-populate the DNS cache, since a synchronous resolution is required in - // order to create the alias. - session_deps_.host_resolver->Resolve( - info, &addresses, CompletionCallback(), NULL, BoundNetLog()); - // Add the alias for the first session's key. Has to be done manually since - // the usual process is bypassed. - pool_peer.AddAlias(addresses.front(), key1); - // Get a session for |key2|, which should return the session created earlier. - scoped_refptr<SpdySession> session2 = - spdy_session_pool_->Get(key2, BoundNetLog()); - ASSERT_EQ(session1.get(), session2.get()); - EXPECT_FALSE(pool->IsStalled()); - - // Release both the pointers to the session so it can be closed. - session1 = NULL; - session2 = NULL; - - // Trying to create a new connection should cause the pool to be stalled, and - // post a task asynchronously to try and close the session. - TestCompletionCallback callback3; - HostPortPair host_port3("3.com", 80); - scoped_refptr<TransportSocketParams> params3( - new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false, - OnHostResolutionCallback())); - scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY, - callback3.callback(), pool, BoundNetLog())); - EXPECT_TRUE(pool->IsStalled()); - - // The socket pool should close the connection asynchronously and establish a - // new connection. - EXPECT_EQ(OK, callback3.WaitForResult()); - EXPECT_FALSE(pool->IsStalled()); -} - -// Tests the case of a non-SPDY request closing an idle SPDY session when a -// pointer to the idle session is still held. -TEST_F(SpdySessionSpdy2Test, CloseOneIdleConnectionSessionStillHeld) { - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - ClientSocketPoolManager::set_max_sockets_per_pool( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - - TransportClientSocketPool* pool = - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL); - - // Create an idle SPDY session. - SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); - EXPECT_FALSE(pool->IsStalled()); - - // Trying to create a new connection should cause the pool to be stalled, and - // post a task asynchronously to try and close the session. - TestCompletionCallback callback2; - HostPortPair host_port2("2.com", 80); - scoped_refptr<TransportSocketParams> params2( - new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, - OnHostResolutionCallback())); - scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, - callback2.callback(), pool, BoundNetLog())); - EXPECT_TRUE(pool->IsStalled()); - - // Running the message loop should cause the session to prepare to be closed, - // but since there's still an outstanding reference, it should not be closed - // yet. - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(pool->IsStalled()); - EXPECT_FALSE(callback2.have_result()); - - // Release the pointer to the session so it can be closed. - session1 = NULL; - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_FALSE(pool->IsStalled()); -} - -// Tests that a non-SPDY request can't close a SPDY session that's currently in -// use. -TEST_F(SpdySessionSpdy2Test, CloseOneIdleConnectionFailsWhenSessionInUse) { - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - ClientSocketPoolManager::set_max_sockets_per_pool( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); - scoped_ptr<SpdyFrame> cancel1( - spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); - MockWrite writes[] = { - CreateMockWrite(*req1, 1), - CreateMockWrite(*cancel1, 1), - }; - StaticSocketDataProvider data(reads, arraysize(reads), - writes, arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - - TransportClientSocketPool* pool = - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL); - - // Create a SPDY session. - GURL url1("http://www.google.com"); - SpdySessionKey key1(HostPortPair(url1.host(), 80), - ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); - EXPECT_FALSE(pool->IsStalled()); - - // Create a stream using the session, and send a request. - - TestCompletionCallback callback1; - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, - session1, url1, DEFAULT_PRIORITY, - BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get()); - test::StreamDelegateDoNothing delegate1(spdy_stream1); - spdy_stream1->SetDelegate(&delegate1); - - scoped_ptr<SpdyHeaderBlock> headers( - spdy_util_.ConstructGetHeaderBlock(url1.spec())); - spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); - EXPECT_TRUE(spdy_stream1->HasUrl()); - base::MessageLoop::current()->RunUntilIdle(); - - // Release the session, so holding onto a pointer here does not affect - // anything. - session1 = NULL; - - // Trying to create a new connection should cause the pool to be stalled, and - // post a task asynchronously to try and close the session. - TestCompletionCallback callback2; - HostPortPair host_port2("2.com", 80); - scoped_refptr<TransportSocketParams> params2( - new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, - OnHostResolutionCallback())); - scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, - callback2.callback(), pool, BoundNetLog())); - EXPECT_TRUE(pool->IsStalled()); - - // Running the message loop should cause the socket pool to ask the SPDY - // session to close an idle socket, but since the socket is in use, nothing - // happens. - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(pool->IsStalled()); - EXPECT_FALSE(callback2.have_result()); - - // Cancelling the request should still not release the session's socket, - // since the session is still kept alive by the SpdySessionPool. - ASSERT_TRUE(spdy_stream1.get()); - spdy_stream1->Cancel(); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(pool->IsStalled()); - EXPECT_FALSE(callback2.have_result()); -} - -} // namespace net diff --git a/net/spdy/spdy_session_spdy3_unittest.cc b/net/spdy/spdy_session_unittest.cc index 961b0bc..b189220 100644 --- a/net/spdy/spdy_session_spdy3_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -23,13 +23,10 @@ #include "net/spdy/spdy_stream.h" #include "net/spdy/spdy_stream_test_util.h" #include "net/spdy/spdy_test_util_common.h" -#include "net/spdy/spdy_test_util_spdy3.h" #include "net/spdy/spdy_test_utils.h" #include "net/test/cert_test_util.h" #include "testing/platform_test.h" -using namespace net::test_spdy3; - namespace net { namespace { @@ -49,9 +46,10 @@ base::TimeTicks TheNearFuture() { } // namespace -class SpdySessionSpdy3Test : public PlatformTest { +class SpdySessionTest : public PlatformTest, + public ::testing::WithParamInterface<NextProto> { public: - // Functions used with RunResumeAfterUnstallTest31(). + // Functions used with RunResumeAfterUnstallTest(). void StallSessionOnly(SpdySession* session, SpdyStream* stream) { StallSessionSend(session); @@ -98,13 +96,13 @@ class SpdySessionSpdy3Test : public PlatformTest { } protected: - SpdySessionSpdy3Test() + SpdySessionTest() : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( HttpNetworkSession::NORMAL_SOCKET_POOL)), old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( HttpNetworkSession::NORMAL_SOCKET_POOL)), - spdy_util_(kProtoSPDY3), - session_deps_(kProtoSPDY3), + spdy_util_(GetParam()), + session_deps_(GetParam()), spdy_session_pool_(NULL), test_url_(kTestUrl), test_host_port_pair_(kTestHost, kTestPort), @@ -112,7 +110,7 @@ class SpdySessionSpdy3Test : public PlatformTest { kPrivacyModeDisabled) { } - virtual ~SpdySessionSpdy3Test() { + virtual ~SpdySessionTest() { // Important to restore the per-pool limit first, since the pool limit must // always be greater than group limit, and the tests reduce both limits. ClientSocketPoolManager::set_max_sockets_per_pool( @@ -145,7 +143,7 @@ class SpdySessionSpdy3Test : public PlatformTest { return session; } - // Creates an initialized session to |pair_|. + // Creates an initialized session to |key_|. scoped_refptr<SpdySession> CreateInitializedSession() { scoped_refptr<SpdySession> session = GetSession(key_); EXPECT_EQ( @@ -195,7 +193,7 @@ class SpdySessionSpdy3Test : public PlatformTest { stream->IncreaseSendWindowSize(delta_window_size); } - void RunResumeAfterUnstallTest31( + void RunResumeAfterUnstallTest( const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, const base::Callback<void(SpdySession*, SpdyStream*, int32)>& unstall_function); @@ -215,7 +213,18 @@ class SpdySessionSpdy3Test : public PlatformTest { SpdySessionKey key_; }; -TEST_F(SpdySessionSpdy3Test, GoAway) { +INSTANTIATE_TEST_CASE_P( + NextProto, + SpdySessionTest, + testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); + +// TODO(akalin): Don't early-exit in the tests below for values > +// kProtoSPDY3. + +TEST_P(SpdySessionTest, GoAway) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -244,7 +253,7 @@ TEST_F(SpdySessionSpdy3Test, GoAway) { scoped_refptr<SpdySession> session = CreateInitializedSession(); - EXPECT_EQ(3, session->GetProtocolVersion()); + EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); GURL url("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -259,14 +268,9 @@ TEST_F(SpdySessionSpdy3Test, GoAway) { test::StreamDelegateDoNothing delegate2(spdy_stream2); spdy_stream2->SetDelegate(&delegate2); - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); - (*headers)[":method"] = "GET"; - (*headers)[":scheme"] = url.scheme(); - (*headers)[":host"] = url.host(); - (*headers)[":path"] = url.path(); - (*headers)[":version"] = "HTTP/1.1"; - scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock); - *headers2 = *headers; + scoped_ptr<SpdyHeaderBlock> headers( + spdy_util_.ConstructGetHeaderBlock(url.spec())); + scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers)); spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); EXPECT_TRUE(spdy_stream1->HasUrl()); @@ -302,7 +306,10 @@ TEST_F(SpdySessionSpdy3Test, GoAway) { EXPECT_EQ(NULL, spdy_stream2.get()); } -TEST_F(SpdySessionSpdy3Test, ClientPing) { +TEST_P(SpdySessionTest, ClientPing) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.enable_ping = true; session_deps_.host_resolver->set_synchronous_mode(true); @@ -358,7 +365,10 @@ TEST_F(SpdySessionSpdy3Test, ClientPing) { session = NULL; } -TEST_F(SpdySessionSpdy3Test, ServerPing) { +TEST_P(SpdySessionTest, ServerPing) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -400,7 +410,10 @@ TEST_F(SpdySessionSpdy3Test, ServerPing) { EXPECT_EQ(NULL, spdy_stream1.get()); } -TEST_F(SpdySessionSpdy3Test, DeleteExpiredPushStreams) { +TEST_P(SpdySessionTest, DeleteExpiredPushStreams) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); SSLSocketDataProvider ssl(SYNCHRONOUS, OK); @@ -411,14 +424,12 @@ TEST_F(SpdySessionSpdy3Test, DeleteExpiredPushStreams) { scoped_refptr<SpdySession> session = GetSession(key_); - // Give the session a SPDY3 framer. - session->buffered_spdy_framer_.reset(new BufferedSpdyFramer(SPDY3, false)); + session->buffered_spdy_framer_.reset( + new BufferedSpdyFramer(spdy_util_.spdy_version(), false)); // Create the associated stream and add to active streams. - scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock); - (*request_headers)[":scheme"] = "http"; - (*request_headers)[":host"] = "www.google.com"; - (*request_headers)[":path"] = "/"; + scoped_ptr<SpdyHeaderBlock> request_headers( + spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); scoped_ptr<SpdyStream> stream(new SpdyStream(SPDY_REQUEST_RESPONSE_STREAM, session.get(), @@ -434,9 +445,7 @@ TEST_F(SpdySessionSpdy3Test, DeleteExpiredPushStreams) { session->InsertActivatedStream(stream.Pass()); SpdyHeaderBlock headers; - headers[":scheme"] = "http"; - headers[":host"] = "www.google.com"; - headers[":path"] = "/a.dat"; + spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat", &headers); session->OnSynStream(2, 1, 0, 0, true, false, headers); // Verify that there is one unclaimed push stream. @@ -448,9 +457,7 @@ TEST_F(SpdySessionSpdy3Test, DeleteExpiredPushStreams) { // Shift time. g_delta_seconds = 301; - headers[":scheme"] = "http"; - headers[":host"] = "www.google.com"; - headers[":path"] = "/b.dat"; + spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat", &headers); session->OnSynStream(4, 1, 0, 0, true, false, headers); // Verify that the second pushed stream evicted the first pushed stream. @@ -462,7 +469,10 @@ TEST_F(SpdySessionSpdy3Test, DeleteExpiredPushStreams) { session = NULL; } -TEST_F(SpdySessionSpdy3Test, FailedPing) { +TEST_P(SpdySessionTest, FailedPing) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -524,7 +534,10 @@ TEST_F(SpdySessionSpdy3Test, FailedPing) { EXPECT_EQ(NULL, spdy_stream1.get()); } -TEST_F(SpdySessionSpdy3Test, CloseIdleSessions) { +TEST_P(SpdySessionTest, CloseIdleSessions) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); MockRead reads[] = { MockRead(ASYNC, 0, 0) // EOF @@ -647,7 +660,10 @@ TEST_F(SpdySessionSpdy3Test, CloseIdleSessions) { // release the stream, which releases its reference (the last) to the session. // Make sure nothing blows up. // http://crbug.com/57331 -TEST_F(SpdySessionSpdy3Test, OnSettings) { +TEST_P(SpdySessionTest, OnSettings) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); SettingsMap new_settings; @@ -705,7 +721,10 @@ TEST_F(SpdySessionSpdy3Test, OnSettings) { // 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. -TEST_F(SpdySessionSpdy3Test, ClearSettings) { +TEST_P(SpdySessionTest, ClearSettings) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); SettingsMap new_settings; @@ -770,13 +789,18 @@ TEST_F(SpdySessionSpdy3Test, ClearSettings) { // Make sure session's max_concurrent_streams is 2. EXPECT_EQ(2u, session->max_concurrent_streams()); + + 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 -TEST_F(SpdySessionSpdy3Test, CancelPendingCreateStream) { +TEST_P(SpdySessionTest, CancelPendingCreateStream) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockRead reads[] = { @@ -831,7 +855,10 @@ TEST_F(SpdySessionSpdy3Test, CancelPendingCreateStream) { base::MessageLoop::current()->RunUntilIdle(); } -TEST_F(SpdySessionSpdy3Test, SendInitialSettingsOnNewSession) { +TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockRead reads[] = { @@ -844,8 +871,10 @@ TEST_F(SpdySessionSpdy3Test, SendInitialSettingsOnNewSession) { const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024; settings[kSpdySettingsIds1] = SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); - settings[kSpdySettingsIds2] = - SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize); + if (spdy_util_.spdy_version() >= SPDY3) { + settings[kSpdySettingsIds2] = + SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize); + } MockConnect connect_data(SYNCHRONOUS, OK); scoped_ptr<SpdyFrame> settings_frame( spdy_util_.ConstructSpdySettings(settings)); @@ -873,7 +902,10 @@ TEST_F(SpdySessionSpdy3Test, SendInitialSettingsOnNewSession) { EXPECT_TRUE(data.at_write_eof()); } -TEST_F(SpdySessionSpdy3Test, SendSettingsOnNewSession) { +TEST_P(SpdySessionTest, SendSettingsOnNewSession) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockRead reads[] = { @@ -949,7 +981,8 @@ void IPPoolingInitializedSession( // sessions are closed with SpdySessionPool::CloseCurrentSessions(). // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS, // sessions are closed with SpdySessionPool::CloseIdleSessions(). -void IPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type) { +void IPPoolingTest(NextProto next_proto, + SpdyPoolCloseSessionsType close_sessions_type) { const int kTestPort = 80; struct TestHosts { std::string url; @@ -972,7 +1005,7 @@ void IPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type) { }, }; - SpdySessionDependencies session_deps(kProtoSPDY3); + SpdySessionDependencies session_deps(next_proto); session_deps.host_resolver->set_synchronous_mode(true); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { session_deps.host_resolver->rules()->AddIPLiteralRule( @@ -985,7 +1018,7 @@ void IPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type) { info, &test_hosts[i].addresses, CompletionCallback(), NULL, BoundNetLog()); - // Setup a HostPortProxyPair + // Setup a SpdySessionKey test_hosts[i].key = SpdySessionKey( HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), kPrivacyModeDisabled); @@ -1157,19 +1190,22 @@ void IPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type) { } // namespace -TEST_F(SpdySessionSpdy3Test, IPPooling) { - IPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY); +TEST_P(SpdySessionTest, IPPooling) { + IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_SESSIONS_MANUALLY); } -TEST_F(SpdySessionSpdy3Test, IPPoolingCloseCurrentSessions) { - IPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS); +TEST_P(SpdySessionTest, IPPoolingCloseCurrentSessions) { + IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_CURRENT_SESSIONS); } -TEST_F(SpdySessionSpdy3Test, IPPoolingCloseIdleSessions) { - IPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS); +TEST_P(SpdySessionTest, IPPoolingCloseIdleSessions) { + IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_IDLE_SESSIONS); } -TEST_F(SpdySessionSpdy3Test, ClearSettingsStorageOnIPAddressChanged) { +TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) { + if (GetParam() > kProtoSPDY3) + return; + CreateNetworkSession(); HttpServerProperties* test_http_server_properties = @@ -1187,7 +1223,10 @@ TEST_F(SpdySessionSpdy3Test, ClearSettingsStorageOnIPAddressChanged) { test_host_port_pair_).size()); } -TEST_F(SpdySessionSpdy3Test, Initialize) { +TEST_P(SpdySessionTest, Initialize) { + if (GetParam() > kProtoSPDY3) + return; + CapturingBoundNetLog log; session_deps_.net_log = log.bound().net_log(); session_deps_.host_resolver->set_synchronous_mode(true); @@ -1236,7 +1275,10 @@ TEST_F(SpdySessionSpdy3Test, Initialize) { EXPECT_NE(log.bound().source().id, socket_source.id); } -TEST_F(SpdySessionSpdy3Test, CloseSessionOnError) { +TEST_P(SpdySessionTest, CloseSessionOnError) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -1286,7 +1328,10 @@ TEST_F(SpdySessionSpdy3Test, CloseSessionOnError) { EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code); } -TEST_F(SpdySessionSpdy3Test, OutOfOrderSynStreams) { +TEST_P(SpdySessionTest, OutOfOrderSynStreams) { + if (GetParam() > kProtoSPDY3) + return; + // Construct the request. MockConnect connect_data(SYNCHRONOUS, OK); scoped_ptr<SpdyFrame> req1( @@ -1298,10 +1343,10 @@ TEST_F(SpdySessionSpdy3Test, OutOfOrderSynStreams) { CreateMockWrite(*req2, 1), }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, true)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); MockRead reads[] = { CreateMockRead(*resp1, 3), CreateMockRead(*body1, 4), @@ -1360,7 +1405,10 @@ TEST_F(SpdySessionSpdy3Test, OutOfOrderSynStreams) { EXPECT_EQ(1u, delegate2.stream_id()); } -TEST_F(SpdySessionSpdy3Test, CancelStream) { +TEST_P(SpdySessionTest, CancelStream) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); // Request 1, at HIGHEST priority, will be cancelled before it writes data. // Request 2, at LOWEST priority, will be a full request and will be id 1. @@ -1370,8 +1418,8 @@ TEST_F(SpdySessionSpdy3Test, CancelStream) { CreateMockWrite(*req2, 0), }; - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(1, true)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); MockRead reads[] = { CreateMockRead(*resp2, 1), CreateMockRead(*body2, 2), @@ -1436,7 +1484,10 @@ TEST_F(SpdySessionSpdy3Test, CancelStream) { EXPECT_EQ(NULL, spdy_stream2.get()); } -TEST_F(SpdySessionSpdy3Test, CloseSessionWithTwoCreatedStreams) { +TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedStreams) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); // Test that if a sesion is closed with two created streams pending, @@ -1509,7 +1560,10 @@ TEST_F(SpdySessionSpdy3Test, CloseSessionWithTwoCreatedStreams) { session = NULL; } -TEST_F(SpdySessionSpdy3Test, VerifyDomainAuthentication) { +TEST_P(SpdySessionTest, VerifyDomainAuthentication) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -1577,7 +1631,10 @@ TEST_F(SpdySessionSpdy3Test, VerifyDomainAuthentication) { EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); } -TEST_F(SpdySessionSpdy3Test, ConnectionPooledWithTlsChannelId) { +TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -1646,7 +1703,10 @@ TEST_F(SpdySessionSpdy3Test, ConnectionPooledWithTlsChannelId) { EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); } -TEST_F(SpdySessionSpdy3Test, CloseTwoStalledCreateStream) { +TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { + if (GetParam() > kProtoSPDY3) + return; + // TODO(rtenneti): Define a helper class/methods and move the common code in // this file. MockConnect connect_data(SYNCHRONOUS, OK); @@ -1674,14 +1734,14 @@ TEST_F(SpdySessionSpdy3Test, CloseTwoStalledCreateStream) { scoped_ptr<SpdyFrame> settings_frame( spdy_util_.ConstructSpdySettings(new_settings)); - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, true)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); - scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5)); - scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(5, true)); + scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); + scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true)); MockRead reads[] = { CreateMockRead(*settings_frame), @@ -1784,7 +1844,10 @@ TEST_F(SpdySessionSpdy3Test, CloseTwoStalledCreateStream) { EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); } -TEST_F(SpdySessionSpdy3Test, CancelTwoStalledCreateStream) { +TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) { + if (GetParam() > kProtoSPDY3) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockRead reads[] = { @@ -1861,7 +1924,10 @@ TEST_F(SpdySessionSpdy3Test, CancelTwoStalledCreateStream) { EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); } -TEST_F(SpdySessionSpdy3Test, NeedsCredentials) { +TEST_P(SpdySessionTest, NeedsCredentials) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); MockRead reads[] = { MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. @@ -1872,12 +1938,12 @@ TEST_F(SpdySessionSpdy3Test, NeedsCredentials) { SSLSocketDataProvider ssl(SYNCHRONOUS, OK); ssl.channel_id_sent = true; - ssl.protocol_negotiated = kProtoSPDY3; + ssl.protocol_negotiated = GetParam(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); CreateNetworkSession(); - const GURL url("https:/www.foo.com"); + const GURL url("https://www.foo.com"); HostPortPair test_host_port_pair(url.host(), 443); SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); @@ -1912,7 +1978,7 @@ TEST_F(SpdySessionSpdy3Test, NeedsCredentials) { EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); - EXPECT_TRUE(session->NeedsCredentials()); + EXPECT_EQ(spdy_util_.spdy_version() >= SPDY3, session->NeedsCredentials()); // Flush the SpdySession::OnReadComplete() task. base::MessageLoop::current()->RunUntilIdle(); @@ -1920,7 +1986,10 @@ TEST_F(SpdySessionSpdy3Test, NeedsCredentials) { spdy_session_pool_->Remove(session); } -TEST_F(SpdySessionSpdy3Test, SendCredentials) { +TEST_P(SpdySessionTest, SendCredentials) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); MockRead reads[] = { MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. @@ -1986,7 +2055,10 @@ TEST_F(SpdySessionSpdy3Test, SendCredentials) { EXPECT_FALSE(spdy_session_pool_->HasSession(key)); } -TEST_F(SpdySessionSpdy3Test, UpdateStreamsSendWindowSize) { +TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) { + if (GetParam() != kProtoSPDY3) + return; + // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE // gets sent. SettingsMap new_settings; @@ -2045,9 +2117,12 @@ TEST_F(SpdySessionSpdy3Test, UpdateStreamsSendWindowSize) { // Test that SpdySession::DoRead reads data from the socket without yielding. // This test makes 32k - 1 bytes of data available on the socket for reading. It // then verifies that it has read all the available data without yielding. -TEST_F(SpdySessionSpdy3Test, ReadDataWithoutYielding) { +TEST_P(SpdySessionTest, ReadDataWithoutYielding) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY3, false); + BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); scoped_ptr<SpdyFrame> req1( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); @@ -2069,7 +2144,7 @@ TEST_F(SpdySessionSpdy3Test, ReadDataWithoutYielding) { scoped_ptr<SpdyFrame> finish_data_frame( framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k // bytes. @@ -2134,9 +2209,12 @@ TEST_F(SpdySessionSpdy3Test, ReadDataWithoutYielding) { // 32k + 1 bytes of data available on the socket for reading. It then verifies // that DoRead has yielded even though there is data available for it to read // (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads). -TEST_F(SpdySessionSpdy3Test, TestYieldingDuringReadData) { +TEST_P(SpdySessionTest, TestYieldingDuringReadData) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY3, false); + BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); scoped_ptr<SpdyFrame> req1( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); @@ -2158,7 +2236,7 @@ TEST_F(SpdySessionSpdy3Test, TestYieldingDuringReadData) { scoped_ptr<SpdyFrame> finish_data_frame( framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); // Write 1 byte more than kMaxReadBytes to check that DoRead yields. MockRead reads[] = { @@ -2231,9 +2309,12 @@ TEST_F(SpdySessionSpdy3Test, TestYieldingDuringReadData) { // (because of async read), so DoRead() will yield. When we come back, DoRead() // will read the results from the async read, and rest of the data // synchronously. -TEST_F(SpdySessionSpdy3Test, TestYieldingDuringAsyncReadData) { +TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY3, false); + BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); scoped_ptr<SpdyFrame> req1( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); @@ -2266,7 +2347,7 @@ TEST_F(SpdySessionSpdy3Test, TestYieldingDuringAsyncReadData) { scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( 1, "h", 1, DATA_FLAG_FIN)); - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); MockRead reads[] = { CreateMockRead(*resp1, 1), @@ -2336,9 +2417,12 @@ TEST_F(SpdySessionSpdy3Test, TestYieldingDuringAsyncReadData) { // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because // GoAway could delete the SpdySession from the SpdySessionPool and the last // reference to SpdySession. -TEST_F(SpdySessionSpdy3Test, GoAwayWhileInDoLoop) { +TEST_P(SpdySessionTest, GoAwayWhileInDoLoop) { + if (GetParam() > kProtoSPDY3) + return; + MockConnect connect_data(SYNCHRONOUS, OK); - BufferedSpdyFramer framer(SPDY3, false); + BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); scoped_ptr<SpdyFrame> req1( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); @@ -2346,8 +2430,8 @@ TEST_F(SpdySessionSpdy3Test, GoAwayWhileInDoLoop) { CreateMockWrite(*req1, 0), }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); MockRead reads[] = { @@ -2403,9 +2487,10 @@ TEST_F(SpdySessionSpdy3Test, GoAwayWhileInDoLoop) { } // Within this framework, a SpdySession should be initialized with -// flow control enabled only for streams and with protocol version 3 -// by default. -TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation) { +// flow control disabled for protocol version 2, with flow control +// enabled only for streams for protocol version 3, and with flow +// control enabled for streams and sessions for higher versions. +TEST_P(SpdySessionTest, ProtocolNegotiation) { session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -2428,82 +2513,24 @@ TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation) { InitializeSession( http_session_.get(), session.get(), test_host_port_pair_); - EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state()); - EXPECT_EQ(SPDY3, session->GetProtocolVersion()); - EXPECT_EQ(0, session->session_send_window_size_); - EXPECT_EQ(0, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); -} - -// Within this framework and with the "enable_spdy_31" flag, a -// SpdySession should be initialized with flow control enabled for -// streams and sessions and with protocol version 3. -TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation31) { - session_deps_.protocol = kProtoSPDY31; - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - - EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); - EXPECT_TRUE(session->buffered_spdy_framer_ == NULL); - EXPECT_EQ(0, session->session_send_window_size_); - EXPECT_EQ(0, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); - - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); - - EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, - session->flow_control_state()); - EXPECT_EQ(SPDY3, session->GetProtocolVersion()); - EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); - EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); -} - -// Within this framework and with the "enable_spdy_4" flag, a -// SpdySession should be initialized with flow control enabled for -// streams and sessions and with protocol version 4. -// -// NOTE(akalin): We are still figuring out the story for SPDY4 test -// coverage. -TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation4) { - session_deps_.protocol = kProtoSPDY4a2; - session_deps_.host_resolver->set_synchronous_mode(true); - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, 0, 0) // EOF - }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); - EXPECT_TRUE(session->buffered_spdy_framer_ == NULL); - EXPECT_EQ(0, session->session_send_window_size_); - EXPECT_EQ(0, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); - - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); - - EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, - session->flow_control_state()); - EXPECT_EQ(SPDY4, session->GetProtocolVersion()); - EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); - EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); + EXPECT_EQ(spdy_util_.spdy_version(), + session->buffered_spdy_framer_->protocol_version()); + if (GetParam() == kProtoSPDY2) { + EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); + EXPECT_EQ(0, session->session_send_window_size_); + EXPECT_EQ(0, session->session_recv_window_size_); + } else if (GetParam() == kProtoSPDY3) { + EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state()); + EXPECT_EQ(0, session->session_send_window_size_); + EXPECT_EQ(0, session->session_recv_window_size_); + } else { + EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, + session->flow_control_state()); + EXPECT_EQ(kSpdySessionInitialWindowSize, + session->session_send_window_size_); + EXPECT_EQ(kDefaultInitialRecvWindowSize, + session->session_recv_window_size_); + } EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); } @@ -2512,8 +2539,10 @@ TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation4) { // flag is set. In addition, SpdySession::IncreaseRecvWindowSize // should trigger sending a WINDOW_UPDATE frame for a large enough // delta. -TEST_F(SpdySessionSpdy3Test, AdjustRecvWindowSize31) { - session_deps_.protocol = kProtoSPDY31; +TEST_P(SpdySessionTest, AdjustRecvWindowSize) { + if (GetParam() < kProtoSPDY31) + return; + session_deps_.host_resolver->set_synchronous_mode(true); const int32 delta_window_size = 100; @@ -2576,8 +2605,10 @@ TEST_F(SpdySessionSpdy3Test, AdjustRecvWindowSize31) { // SpdySession::{Increase,Decrease}SendWindowSize should properly // adjust the session send window size when the "enable_spdy_31" flag // is set. -TEST_F(SpdySessionSpdy3Test, AdjustSendWindowSize31) { - session_deps_.protocol = kProtoSPDY31; +TEST_P(SpdySessionTest, AdjustSendWindowSize) { + if (GetParam() < kProtoSPDY31) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); @@ -2609,12 +2640,14 @@ TEST_F(SpdySessionSpdy3Test, AdjustSendWindowSize31) { // Incoming data for an inactive stream should not cause the session // receive window size to decrease. -TEST_F(SpdySessionSpdy3Test, SessionFlowControlInactiveStream31) { - session_deps_.protocol = kProtoSPDY31; +TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) { + if (GetParam() < kProtoSPDY31) + return; + session_deps_.host_resolver->set_synchronous_mode(true); MockConnect connect_data(SYNCHRONOUS, OK); - scoped_ptr<SpdyFrame> resp(ConstructSpdyBodyFrame(1, false)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false)); MockRead reads[] = { CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 2) // EOF @@ -2668,10 +2701,11 @@ class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate { // Send data back and forth but use a delegate that drops its received // data. The receive window should still increase to its original // value, i.e. we shouldn't "leak" receive window bytes. -TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoReceiveLeaks31) { - const char kStreamUrl[] = "http://www.google.com/"; +TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) { + if (GetParam() < kProtoSPDY31) + return; - session_deps_.protocol = kProtoSPDY31; + const char kStreamUrl[] = "http://www.google.com/"; const int32 msg_data_size = 100; const std::string msg_data(msg_data_size, 'a'); @@ -2683,18 +2717,21 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoReceiveLeaks31) { kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req( - ConstructSpdyPost(kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); scoped_ptr<SpdyFrame> msg( - ConstructSpdyBodyFrame(1, msg_data.data(), msg_data_size, false)); + spdy_util_.ConstructSpdyBodyFrame( + 1, msg_data.data(), msg_data_size, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req, 1), CreateMockWrite(*msg, 3), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> echo( - ConstructSpdyBodyFrame(1, msg_data.data(), msg_data_size, false)); + spdy_util_.ConstructSpdyBodyFrame( + 1, msg_data.data(), msg_data_size, false)); scoped_ptr<SpdyFrame> window_update( spdy_util_.ConstructSpdyWindowUpdate( kSessionFlowControlStreamId, msg_data_size)); @@ -2757,10 +2794,11 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoReceiveLeaks31) { // Send data back and forth but close the stream before its data frame // can be written to the socket. The send window should then increase // to its original value, i.e. we shouldn't "leak" send window bytes. -TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoSendLeaks31) { - const char kStreamUrl[] = "http://www.google.com/"; +TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) { + if (GetParam() < kProtoSPDY31) + return; - session_deps_.protocol = kProtoSPDY31; + const char kStreamUrl[] = "http://www.google.com/"; const int32 msg_data_size = 100; const std::string msg_data(msg_data_size, 'a'); @@ -2772,13 +2810,14 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoSendLeaks31) { kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req( - ConstructSpdyPost(kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req, 1), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); MockRead reads[] = { CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF @@ -2839,10 +2878,11 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoSendLeaks31) { // Send data back and forth; the send and receive windows should // change appropriately. -TEST_F(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31) { - const char kStreamUrl[] = "http://www.google.com/"; +TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) { + if (GetParam() < kProtoSPDY31) + return; - session_deps_.protocol = kProtoSPDY31; + const char kStreamUrl[] = "http://www.google.com/"; const int32 msg_data_size = 100; const std::string msg_data(msg_data_size, 'a'); @@ -2854,18 +2894,21 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31) { kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req( - ConstructSpdyPost(kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); scoped_ptr<SpdyFrame> msg( - ConstructSpdyBodyFrame(1, msg_data.data(), msg_data_size, false)); + spdy_util_.ConstructSpdyBodyFrame( + 1, msg_data.data(), msg_data_size, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req, 1), CreateMockWrite(*msg, 3), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> echo( - ConstructSpdyBodyFrame(1, msg_data.data(), msg_data_size, false)); + spdy_util_.ConstructSpdyBodyFrame( + 1, msg_data.data(), msg_data_size, false)); scoped_ptr<SpdyFrame> window_update( spdy_util_.ConstructSpdyWindowUpdate( kSessionFlowControlStreamId, msg_data_size)); @@ -2968,14 +3011,13 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31) { // Given a stall function and an unstall function, runs a test to make // sure that a stream resumes after unstall. -void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( +void SpdySessionTest::RunResumeAfterUnstallTest( const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, const base::Callback<void(SpdySession*, SpdyStream*, int32)>& unstall_function) { const char kStreamUrl[] = "http://www.google.com/"; GURL url(kStreamUrl); - session_deps_.protocol = kProtoSPDY31; session_deps_.host_resolver->set_synchronous_mode(true); scoped_ptr<SpdyFrame> initial_window_update( @@ -2983,18 +3025,20 @@ void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req( - ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> body( - ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); + spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req, 1), CreateMockWrite(*body, 2), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp( + spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> echo( - ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); + spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); MockRead reads[] = { CreateMockRead(*resp, 3), MockRead(ASYNC, 0, 0, 4), // EOF @@ -3056,68 +3100,84 @@ void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( // Run the resume-after-unstall test with all possible stall and // unstall sequences. -TEST_F(SpdySessionSpdy3Test, ResumeAfterUnstallSession31) { - RunResumeAfterUnstallTest31( - base::Bind(&SpdySessionSpdy3Test::StallSessionOnly, +TEST_P(SpdySessionTest, ResumeAfterUnstallSession) { + if (GetParam() < kProtoSPDY31) + return; + + RunResumeAfterUnstallTest( + base::Bind(&SpdySessionTest::StallSessionOnly, base::Unretained(this)), - base::Bind(&SpdySessionSpdy3Test::UnstallSessionOnly, + base::Bind(&SpdySessionTest::UnstallSessionOnly, base::Unretained(this))); } // Equivalent to -// SpdyStreamSpdy3Test.ResumeAfterSendWindowSizeIncrease. -TEST_F(SpdySessionSpdy3Test, ResumeAfterUnstallStream31) { - RunResumeAfterUnstallTest31( - base::Bind(&SpdySessionSpdy3Test::StallStreamOnly, +// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease. +TEST_P(SpdySessionTest, ResumeAfterUnstallStream) { + if (GetParam() < kProtoSPDY31) + return; + + RunResumeAfterUnstallTest( + base::Bind(&SpdySessionTest::StallStreamOnly, base::Unretained(this)), - base::Bind(&SpdySessionSpdy3Test::UnstallStreamOnly, + base::Bind(&SpdySessionTest::UnstallStreamOnly, base::Unretained(this))); } -TEST_F(SpdySessionSpdy3Test, - StallSessionStreamResumeAfterUnstallSessionStream31) { - RunResumeAfterUnstallTest31( - base::Bind(&SpdySessionSpdy3Test::StallSessionStream, +TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) { + if (GetParam() < kProtoSPDY31) + return; + + RunResumeAfterUnstallTest( + base::Bind(&SpdySessionTest::StallSessionStream, base::Unretained(this)), - base::Bind(&SpdySessionSpdy3Test::UnstallSessionStream, + base::Bind(&SpdySessionTest::UnstallSessionStream, base::Unretained(this))); } -TEST_F(SpdySessionSpdy3Test, - StallStreamSessionResumeAfterUnstallSessionStream31) { - RunResumeAfterUnstallTest31( - base::Bind(&SpdySessionSpdy3Test::StallStreamSession, +TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) { + if (GetParam() < kProtoSPDY31) + return; + + RunResumeAfterUnstallTest( + base::Bind(&SpdySessionTest::StallStreamSession, base::Unretained(this)), - base::Bind(&SpdySessionSpdy3Test::UnstallSessionStream, + base::Bind(&SpdySessionTest::UnstallSessionStream, base::Unretained(this))); } -TEST_F(SpdySessionSpdy3Test, - StallStreamSessionResumeAfterUnstallStreamSession31) { - RunResumeAfterUnstallTest31( - base::Bind(&SpdySessionSpdy3Test::StallStreamSession, +TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) { + if (GetParam() < kProtoSPDY31) + return; + + RunResumeAfterUnstallTest( + base::Bind(&SpdySessionTest::StallStreamSession, base::Unretained(this)), - base::Bind(&SpdySessionSpdy3Test::UnstallStreamSession, + base::Bind(&SpdySessionTest::UnstallStreamSession, base::Unretained(this))); } -TEST_F(SpdySessionSpdy3Test, - StallSessionStreamResumeAfterUnstallStreamSession31) { - RunResumeAfterUnstallTest31( - base::Bind(&SpdySessionSpdy3Test::StallSessionStream, +TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) { + if (GetParam() < kProtoSPDY31) + return; + + RunResumeAfterUnstallTest( + base::Bind(&SpdySessionTest::StallSessionStream, base::Unretained(this)), - base::Bind(&SpdySessionSpdy3Test::UnstallStreamSession, + base::Bind(&SpdySessionTest::UnstallStreamSession, base::Unretained(this))); } // Cause a stall by reducing the flow control send window to 0. The // streams should resume in priority order when that window is then // increased. -TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { +TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) { + if (GetParam() < kProtoSPDY31) + return; + const char kStreamUrl[] = "http://www.google.com/"; GURL url(kStreamUrl); - session_deps_.protocol = kProtoSPDY31; session_deps_.host_resolver->set_synchronous_mode(true); scoped_ptr<SpdyFrame> initial_window_update( @@ -3125,13 +3185,15 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req1( - ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req2( - ConstructSpdyPost(kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0)); scoped_ptr<SpdyFrame> body1( - ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); + spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); scoped_ptr<SpdyFrame> body2( - ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); + spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req1, 1), @@ -3140,8 +3202,8 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { CreateMockWrite(*body1, 4), }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); MockRead reads[] = { CreateMockRead(*resp1, 5), CreateMockRead(*resp2, 6), @@ -3271,11 +3333,13 @@ class StreamClosingDelegate : public test::StreamDelegateWithBody { // Cause a stall by reducing the flow control send window to // 0. Unstalling the session should properly handle deleted streams. -TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { +TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) { + if (GetParam() < kProtoSPDY31) + return; + const char kStreamUrl[] = "http://www.google.com/"; GURL url(kStreamUrl); - session_deps_.protocol = kProtoSPDY31; session_deps_.host_resolver->set_synchronous_mode(true); scoped_ptr<SpdyFrame> initial_window_update( @@ -3283,13 +3347,16 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req1( - ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req2( - ConstructSpdyPost(kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req3( - ConstructSpdyPost(kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> body2( - ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); + spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req1, 1), @@ -3298,7 +3365,7 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { CreateMockWrite(*body2, 4), }; - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); MockRead reads[] = { CreateMockRead(*resp2, 5), MockRead(ASYNC, 0, 0, 6), // EOF @@ -3435,11 +3502,13 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { // Cause a stall by reducing the flow control send window to // 0. Unstalling the session should properly handle the session itself // being closed. -TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { +TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { + if (GetParam() < kProtoSPDY31) + return; + const char kStreamUrl[] = "http://www.google.com/"; GURL url(kStreamUrl); - session_deps_.protocol = kProtoSPDY31; session_deps_.host_resolver->set_synchronous_mode(true); scoped_ptr<SpdyFrame> initial_window_update( @@ -3447,11 +3516,13 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req1( - ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req2( - ConstructSpdyPost(kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); + spdy_util_.ConstructSpdyPost( + kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> body1( - ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); + spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req1, 1), @@ -3549,7 +3620,10 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { // Tests the case of a non-SPDY request closing an idle SPDY session when no // pointers to the idle session are currently held. -TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnection) { +TEST_P(SpdySessionTest, CloseOneIdleConnection) { + if (GetParam() > kProtoSPDY3) + return; + ClientSocketPoolManager::set_max_sockets_per_group( HttpNetworkSession::NORMAL_SOCKET_POOL, 1); ClientSocketPoolManager::set_max_sockets_per_pool( @@ -3604,7 +3678,10 @@ TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnection) { // Tests the case of a non-SPDY request closing an idle SPDY session when no // pointers to the idle session are currently held, in the case the SPDY session // has an alias. -TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnectionWithAlias) { +TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) { + if (GetParam() > kProtoSPDY3) + return; + ClientSocketPoolManager::set_max_sockets_per_group( HttpNetworkSession::NORMAL_SOCKET_POOL, 1); ClientSocketPoolManager::set_max_sockets_per_pool( @@ -3688,7 +3765,10 @@ TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnectionWithAlias) { // Tests the case of a non-SPDY request closing an idle SPDY session when a // pointer to the idle session is still held. -TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnectionSessionStillHeld) { +TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) { + if (GetParam() > kProtoSPDY3) + return; + ClientSocketPoolManager::set_max_sockets_per_group( HttpNetworkSession::NORMAL_SOCKET_POOL, 1); ClientSocketPoolManager::set_max_sockets_per_pool( @@ -3747,7 +3827,10 @@ TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnectionSessionStillHeld) { // Tests that a non-SPDY request can't close a SPDY session that's currently in // use. -TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnectionFailsWhenSessionInUse) { +TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) { + if (GetParam() > kProtoSPDY3) + return; + ClientSocketPoolManager::set_max_sockets_per_group( HttpNetworkSession::NORMAL_SOCKET_POOL, 1); ClientSocketPoolManager::set_max_sockets_per_pool( @@ -3842,7 +3925,7 @@ TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnectionFailsWhenSessionInUse) { // Verify that SpdySessionKey and therefore SpdySession is different when // privacy mode is enabled or disabled. -TEST_F(SpdySessionSpdy3Test, SpdySessionKeyPrivacyMode) { +TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) { CreateDeterministicNetworkSession(); HostPortPair host_port_pair("www.google.com", 443); diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index b684cc0..9992c18 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -129,7 +129,7 @@ class SpdyStreamTest : public ::testing::Test, INSTANTIATE_TEST_CASE_P( NextProto, SpdyStreamTest, - testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31)); + testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); TEST_P(SpdyStreamTest, SendDataAfterOpen) { GURL url(kStreamUrl); |