summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_session_spdy2_unittest.cc
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-11 21:23:34 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-11 21:23:34 +0000
commit162deb8fa72342e8dae1c4793f9b6c4630af2a47 (patch)
treed6bbb6cf9d69e5c9e96158926368ed37b85f85c6 /net/spdy/spdy_session_spdy2_unittest.cc
parent3774f835ddbe5005ad49c5a1818b3fcbfff4f703 (diff)
downloadchromium_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/spdy_session_spdy2_unittest.cc')
-rw-r--r--net/spdy/spdy_session_spdy2_unittest.cc2498
1 files changed, 0 insertions, 2498 deletions
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