Clone of chromium aad1ce808763f59c7a3753e08f1500a104ecc6fd refs/remotes/origin/HEAD
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
new file mode 100644
index 0000000..ece3e64
--- /dev/null
+++ b/net/quic/quic_stream_factory_test.cc
@@ -0,0 +1,1513 @@
+// 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/quic/quic_stream_factory.h"
+
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/cert_verifier.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
+#include "net/http/http_util.h"
+#include "net/http/transport_security_state.h"
+#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/crypto/proof_verifier_chromium.h"
+#include "net/quic/crypto/quic_decrypter.h"
+#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/quic_http_stream.h"
+#include "net/quic/quic_server_id.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
+#include "net/quic/test_tools/mock_random.h"
+#include "net/quic/test_tools/quic_test_packet_maker.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_test_utils.h"
+#include "net/ssl/channel_id_service.h"
+#include "net/ssl/default_channel_id_store.h"
+#include "net/test/cert_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+using std::vector;
+
+namespace net {
+namespace test {
+
+namespace {
+const char kDefaultServerHostName[] = "www.google.com";
+const int kDefaultServerPort = 443;
+}  // namespace anonymous
+
+class QuicStreamFactoryPeer {
+ public:
+  static QuicCryptoClientConfig* GetCryptoConfig(QuicStreamFactory* factory) {
+    return &factory->crypto_config_;
+  }
+
+  static bool HasActiveSession(QuicStreamFactory* factory,
+                               const HostPortPair& host_port_pair,
+                               bool is_https) {
+    QuicServerId server_id(host_port_pair, is_https, PRIVACY_MODE_DISABLED);
+    return factory->HasActiveSession(server_id);
+  }
+
+  static QuicClientSession* GetActiveSession(
+      QuicStreamFactory* factory,
+      const HostPortPair& host_port_pair,
+      bool is_https) {
+    QuicServerId server_id(host_port_pair, is_https, PRIVACY_MODE_DISABLED);
+    DCHECK(factory->HasActiveSession(server_id));
+    return factory->active_sessions_[server_id];
+  }
+
+  static scoped_ptr<QuicHttpStream> CreateIfSessionExists(
+      QuicStreamFactory* factory,
+      const HostPortPair& host_port_pair,
+      bool is_https,
+      const BoundNetLog& net_log) {
+    QuicServerId server_id(host_port_pair, is_https, PRIVACY_MODE_DISABLED);
+    return factory->CreateIfSessionExists(server_id, net_log);
+  }
+
+  static bool IsLiveSession(QuicStreamFactory* factory,
+                            QuicClientSession* session) {
+    for (QuicStreamFactory::SessionIdMap::iterator it =
+             factory->all_sessions_.begin();
+         it != factory->all_sessions_.end(); ++it) {
+      if (it->first == session)
+        return true;
+    }
+    return false;
+  }
+
+  static void DisableConnectionPooling(QuicStreamFactory* factory) {
+    factory->disable_connection_pooling_ = true;
+  }
+};
+
+class QuicStreamFactoryTest : public ::testing::TestWithParam<QuicVersion> {
+ protected:
+  QuicStreamFactoryTest()
+      : random_generator_(0),
+        clock_(new MockClock()),
+        maker_(GetParam(), 0, clock_),
+        cert_verifier_(CertVerifier::CreateDefault()),
+        channel_id_service_(
+            new ChannelIDService(new DefaultChannelIDStore(nullptr),
+                                 base::MessageLoopProxy::current())),
+        factory_(&host_resolver_,
+                 &socket_factory_,
+                 base::WeakPtr<HttpServerProperties>(),
+                 cert_verifier_.get(),
+                 channel_id_service_.get(),
+                 &transport_security_state_,
+                 &crypto_client_stream_factory_,
+                 &random_generator_,
+                 clock_,
+                 kDefaultMaxPacketSize,
+                 std::string(),
+                 SupportedVersions(GetParam()),
+                 /*enable_port_selection=*/true,
+                 /*always_require_handshake_confirmation=*/false,
+                 /*disable_connection_pooling=*/false,
+                 QuicTagVector()),
+        host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
+        is_https_(false),
+        privacy_mode_(PRIVACY_MODE_DISABLED) {
+    factory_.set_require_confirmation(false);
+    clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+  }
+
+  scoped_ptr<QuicHttpStream> CreateIfSessionExists(
+      const HostPortPair& host_port_pair,
+      const BoundNetLog& net_log) {
+    return QuicStreamFactoryPeer::CreateIfSessionExists(
+        &factory_, host_port_pair, false, net_log_);
+  }
+
+  int GetSourcePortForNewSession(const HostPortPair& destination) {
+    return GetSourcePortForNewSessionInner(destination, false);
+  }
+
+  int GetSourcePortForNewSessionAndGoAway(
+      const HostPortPair& destination) {
+    return GetSourcePortForNewSessionInner(destination, true);
+  }
+
+  int GetSourcePortForNewSessionInner(const HostPortPair& destination,
+                                      bool goaway_received) {
+    // Should only be called if there is no active session for this destination.
+    EXPECT_EQ(nullptr, CreateIfSessionExists(destination, net_log_).get());
+    size_t socket_count = socket_factory_.udp_client_sockets().size();
+
+    MockRead reads[] = {
+      MockRead(ASYNC, OK, 0)  // EOF
+    };
+    DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+    socket_data.StopAfter(1);
+    socket_factory_.AddSocketDataProvider(&socket_data);
+
+    QuicStreamRequest request(&factory_);
+    EXPECT_EQ(ERR_IO_PENDING,
+              request.Request(destination,
+                              is_https_,
+                              privacy_mode_,
+                              "GET",
+                              net_log_,
+                              callback_.callback()));
+
+    EXPECT_EQ(OK, callback_.WaitForResult());
+    scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+    EXPECT_TRUE(stream.get());
+    stream.reset();
+
+    QuicClientSession* session = QuicStreamFactoryPeer::GetActiveSession(
+        &factory_, destination, is_https_);
+
+    if (socket_count + 1 != socket_factory_.udp_client_sockets().size()) {
+      EXPECT_TRUE(false);
+      return 0;
+    }
+
+    IPEndPoint endpoint;
+    socket_factory_.
+        udp_client_sockets()[socket_count]->GetLocalAddress(&endpoint);
+    int port = endpoint.port();
+    if (goaway_received) {
+      QuicGoAwayFrame goaway(QUIC_NO_ERROR, 1, "");
+      session->OnGoAway(goaway);
+    }
+
+    factory_.OnSessionClosed(session);
+    EXPECT_EQ(nullptr, CreateIfSessionExists(destination, net_log_).get());
+    EXPECT_TRUE(socket_data.at_read_eof());
+    EXPECT_TRUE(socket_data.at_write_eof());
+    return port;
+  }
+
+  scoped_ptr<QuicEncryptedPacket> ConstructRstPacket() {
+    QuicStreamId stream_id = kClientDataStreamId1;
+    return maker_.MakeRstPacket(
+        1, true, stream_id,
+        AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
+  }
+
+  MockHostResolver host_resolver_;
+  DeterministicMockClientSocketFactory socket_factory_;
+  MockCryptoClientStreamFactory crypto_client_stream_factory_;
+  MockRandom random_generator_;
+  MockClock* clock_;  // Owned by factory_.
+  QuicTestPacketMaker maker_;
+  scoped_ptr<CertVerifier> cert_verifier_;
+  scoped_ptr<ChannelIDService> channel_id_service_;
+  TransportSecurityState transport_security_state_;
+  QuicStreamFactory factory_;
+  HostPortPair host_port_pair_;
+  bool is_https_;
+  PrivacyMode privacy_mode_;
+  BoundNetLog net_log_;
+  TestCompletionCallback callback_;
+};
+
+INSTANTIATE_TEST_CASE_P(Version, QuicStreamFactoryTest,
+                        ::testing::ValuesIn(QuicSupportedVersions()));
+
+TEST_P(QuicStreamFactoryTest, CreateIfSessionExists) {
+  EXPECT_EQ(nullptr, CreateIfSessionExists(host_port_pair_, net_log_).get());
+}
+
+TEST_P(QuicStreamFactoryTest, Create) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  // Will reset stream 3.
+  stream = CreateIfSessionExists(host_port_pair_, net_log_);
+  EXPECT_TRUE(stream.get());
+
+  // TODO(rtenneti): We should probably have a tests that HTTP and HTTPS result
+  // in streams on different sessions.
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  stream = request2.ReleaseStream();  // Will reset stream 5.
+  stream.reset();  // Will reset stream 7.
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, CreateZeroRttPost) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  // Posts require handshake confirmation, so this will return asynchronously.
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "POST",
+                            net_log_,
+                            callback_.callback()));
+
+  // Confirm the handshake and verify that the stream is created.
+  crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
+      QuicSession::HANDSHAKE_CONFIRMED);
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, CreateHttpVsHttps) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_,
+                             !is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  stream = request2.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  stream.reset();
+
+  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, host_port_pair_, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, host_port_pair_, !is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, Pooling) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  HostPortPair server2("mail.google.com", kDefaultServerPort);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(
+      kDefaultServerHostName, "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(
+      "mail.google.com", "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_EQ(
+      QuicStreamFactoryPeer::GetActiveSession(
+          &factory_, host_port_pair_, is_https_),
+      QuicStreamFactoryPeer::GetActiveSession(&factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoPoolingIfDisabled) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  HostPortPair server2("mail.google.com", kDefaultServerPort);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(
+      kDefaultServerHostName, "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(
+      "mail.google.com", "192.168.0.1", "");
+
+  // Disable connection pooling.
+  QuicStreamFactoryPeer::DisableConnectionPooling(&factory_);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_NE(
+      QuicStreamFactoryPeer::GetActiveSession(
+          &factory_, host_port_pair_, is_https_),
+      QuicStreamFactoryPeer::GetActiveSession(&factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  HostPortPair server2("mail.google.com", kDefaultServerPort);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(
+      kDefaultServerHostName, "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(
+      "mail.google.com", "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  factory_.OnSessionGoingAway(QuicStreamFactoryPeer::GetActiveSession(
+      &factory_, host_port_pair_, is_https_));
+  EXPECT_FALSE(QuicStreamFactoryPeer::HasActiveSession(
+      &factory_, host_port_pair_, is_https_));
+  EXPECT_FALSE(QuicStreamFactoryPeer::HasActiveSession(
+      &factory_, server2, is_https_));
+
+  TestCompletionCallback callback3;
+  QuicStreamRequest request3(&factory_);
+  EXPECT_EQ(OK,
+            request3.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback3.callback()));
+  scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
+  EXPECT_TRUE(stream3.get());
+
+  EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(
+      &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, HttpsPooling) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  HostPortPair server1("www.example.org", 443);
+  HostPortPair server2("mail.example.org", 443);
+
+  // Load a cert that is valid for:
+  //   www.example.org (server1)
+  //   mail.example.org (server2)
+  //   www.example.com
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+  ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
+  ProofVerifyDetailsChromium verify_details;
+  verify_details.cert_verify_result.verified_cert = test_cert;
+  verify_details.cert_verify_result.is_issued_by_known_root = true;
+  crypto_client_stream_factory_.set_proof_verify_details(&verify_details);
+
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  is_https_ = true;
+  EXPECT_EQ(OK,
+            request.Request(server1,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server1, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoHttpsPoolingIfDisabled) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  HostPortPair server1("www.example.org", 443);
+  HostPortPair server2("mail.example.org", 443);
+
+  // Load a cert that is valid for:
+  //   www.example.org (server1)
+  //   mail.example.org (server2)
+  //   www.example.com
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+  ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
+  ProofVerifyDetailsChromium verify_details;
+  verify_details.cert_verify_result.verified_cert = test_cert;
+  verify_details.cert_verify_result.is_issued_by_known_root = true;
+  crypto_client_stream_factory_.set_proof_verify_details(&verify_details);
+
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
+
+  // Disable connection pooling.
+  QuicStreamFactoryPeer::DisableConnectionPooling(&factory_);
+
+  QuicStreamRequest request(&factory_);
+  is_https_ = true;
+  EXPECT_EQ(OK,
+            request.Request(server1,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server1, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithCertMismatch) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  HostPortPair server1("www.example.org", 443);
+  HostPortPair server2("mail.google.com", 443);
+
+  // Load a cert that is valid for:
+  //   www.example.org (server1)
+  //   mail.example.org
+  //   www.example.com
+  // But is not valid for mail.google.com (server2).
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+  ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
+  ProofVerifyDetailsChromium verify_details;
+  verify_details.cert_verify_result.verified_cert = test_cert;
+  crypto_client_stream_factory_.set_proof_verify_details(&verify_details);
+
+
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  is_https_ = true;
+  EXPECT_EQ(OK,
+            request.Request(server1,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server1, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, HttpsPoolingWithMatchingPins) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  HostPortPair server1("www.example.org", 443);
+  HostPortPair server2("mail.example.org", 443);
+  uint8 primary_pin = 1;
+  uint8 backup_pin = 2;
+  test::AddPin(&transport_security_state_, "mail.example.org", primary_pin,
+               backup_pin);
+
+  // Load a cert that is valid for:
+  //   www.example.org (server1)
+  //   mail.example.org (server2)
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+  ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
+  ProofVerifyDetailsChromium verify_details;
+  verify_details.cert_verify_result.verified_cert = test_cert;
+  verify_details.cert_verify_result.is_issued_by_known_root = true;
+  verify_details.cert_verify_result.public_key_hashes.push_back(
+      test::GetTestHashValue(primary_pin));
+  crypto_client_stream_factory_.set_proof_verify_details(&verify_details);
+
+
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  is_https_ = true;
+  EXPECT_EQ(OK,
+            request.Request(server1,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server1, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithMatchingPinsIfDisabled) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  HostPortPair server1("www.example.org", 443);
+  HostPortPair server2("mail.example.org", 443);
+  uint8 primary_pin = 1;
+  uint8 backup_pin = 2;
+  test::AddPin(&transport_security_state_, "mail.example.org", primary_pin,
+               backup_pin);
+
+  // Load a cert that is valid for:
+  //   www.example.org (server1)
+  //   mail.example.org (server2)
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+  ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
+  ProofVerifyDetailsChromium verify_details;
+  verify_details.cert_verify_result.verified_cert = test_cert;
+  verify_details.cert_verify_result.is_issued_by_known_root = true;
+  verify_details.cert_verify_result.public_key_hashes.push_back(
+      test::GetTestHashValue(primary_pin));
+  crypto_client_stream_factory_.set_proof_verify_details(&verify_details);
+
+
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
+
+  // Disable connection pooling.
+  QuicStreamFactoryPeer::DisableConnectionPooling(&factory_);
+
+  QuicStreamRequest request(&factory_);
+  is_https_ = true;
+  EXPECT_EQ(OK,
+            request.Request(server1,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server1, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithDifferentPins) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data1(reads, arraysize(reads), nullptr, 0);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data1.StopAfter(1);
+  socket_data2.StopAfter(1);
+
+  HostPortPair server1("www.example.org", 443);
+  HostPortPair server2("mail.example.org", 443);
+  uint8 primary_pin = 1;
+  uint8 backup_pin = 2;
+  uint8 bad_pin = 3;
+  test::AddPin(&transport_security_state_, "mail.example.org", primary_pin,
+               backup_pin);
+
+  // Load a cert that is valid for:
+  //   www.example.org (server1)
+  //   mail.example.org (server2)
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+  ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
+  ProofVerifyDetailsChromium verify_details;
+  verify_details.cert_verify_result.verified_cert = test_cert;
+  verify_details.cert_verify_result.is_issued_by_known_root = true;
+  verify_details.cert_verify_result.public_key_hashes.push_back(
+      test::GetTestHashValue(bad_pin));
+  crypto_client_stream_factory_.set_proof_verify_details(&verify_details);
+
+
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", "");
+  host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  is_https_ = true;
+  EXPECT_EQ(OK,
+            request.Request(server1,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  TestCompletionCallback callback;
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(OK,
+            request2.Request(server2,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server1, is_https_),
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, server2, is_https_));
+
+  EXPECT_TRUE(socket_data1.at_read_eof());
+  EXPECT_TRUE(socket_data1.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, Goaway) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_data.StopAfter(1);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  DeterministicSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+  socket_data2.StopAfter(1);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+
+  // Mark the session as going away.  Ensure that while it is still alive
+  // that it is no longer active.
+  QuicClientSession* session = QuicStreamFactoryPeer::GetActiveSession(
+      &factory_, host_port_pair_, is_https_);
+  factory_.OnSessionGoingAway(session);
+  EXPECT_EQ(true, QuicStreamFactoryPeer::IsLiveSession(&factory_, session));
+  EXPECT_FALSE(QuicStreamFactoryPeer::HasActiveSession(
+      &factory_, host_port_pair_, is_https_));
+  EXPECT_EQ(nullptr, CreateIfSessionExists(host_port_pair_, net_log_).get());
+
+  // Create a new request for the same destination and verify that a
+  // new session is created.
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+  EXPECT_TRUE(stream2.get());
+
+  EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(&factory_,
+                                                      host_port_pair_,
+                                                      is_https_));
+  EXPECT_NE(session,
+            QuicStreamFactoryPeer::GetActiveSession(
+                &factory_, host_port_pair_, is_https_));
+  EXPECT_EQ(true, QuicStreamFactoryPeer::IsLiveSession(&factory_, session));
+
+  stream2.reset();
+  stream.reset();
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  QuicStreamId stream_id = kClientDataStreamId1;
+  scoped_ptr<QuicEncryptedPacket> rst(
+      maker_.MakeRstPacket(1, true, stream_id, QUIC_STREAM_CANCELLED));
+  MockWrite writes[] = {
+    MockWrite(ASYNC, rst->data(), rst->length(), 1),
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads),
+                                      writes, arraysize(writes));
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  HttpRequestInfo request_info;
+  std::vector<QuicHttpStream*> streams;
+  // The MockCryptoClientStream sets max_open_streams to be
+  // 2 * kDefaultMaxStreamsPerConnection.
+  for (size_t i = 0; i < 2 * kDefaultMaxStreamsPerConnection; i++) {
+    QuicStreamRequest request(&factory_);
+    int rv = request.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback());
+    if (i == 0) {
+      EXPECT_EQ(ERR_IO_PENDING, rv);
+      EXPECT_EQ(OK, callback_.WaitForResult());
+    } else {
+      EXPECT_EQ(OK, rv);
+    }
+    scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+    EXPECT_TRUE(stream);
+    EXPECT_EQ(OK, stream->InitializeStream(
+        &request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback()));
+    streams.push_back(stream.release());
+  }
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            CompletionCallback()));
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream);
+  EXPECT_EQ(ERR_IO_PENDING, stream->InitializeStream(
+        &request_info, DEFAULT_PRIORITY, net_log_, callback_.callback()));
+
+  // Close the first stream.
+  streams.front()->Close(false);
+
+  ASSERT_TRUE(callback_.have_result());
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+  STLDeleteElements(&streams);
+}
+
+TEST_P(QuicStreamFactoryTest, ResolutionErrorInCreate) {
+  DeterministicSocketData socket_data(nullptr, 0, nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+
+  host_resolver_.rules()->AddSimulatedFailure(kDefaultServerHostName);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback_.WaitForResult());
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, ConnectErrorInCreate) {
+  MockConnect connect(SYNCHRONOUS, ERR_ADDRESS_IN_USE);
+  DeterministicSocketData socket_data(nullptr, 0, nullptr, 0);
+  socket_data.set_connect_data(connect);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(ERR_ADDRESS_IN_USE, callback_.WaitForResult());
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, CancelCreate) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  {
+    QuicStreamRequest request(&factory_);
+    EXPECT_EQ(ERR_IO_PENDING,
+              request.Request(host_port_pair_,
+                              is_https_,
+                              privacy_mode_,
+                              "GET",
+                              net_log_,
+                              callback_.callback()));
+  }
+
+  socket_data.StopAfter(1);
+  base::RunLoop run_loop;
+  run_loop.RunUntilIdle();
+
+  scoped_ptr<QuicHttpStream> stream(
+      CreateIfSessionExists(host_port_pair_, net_log_));
+  EXPECT_TRUE(stream.get());
+  stream.reset();
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, CreateConsistentEphemeralPort) {
+  // Sequentially connect to the default host, then another host, and then the
+  // default host.  Verify that the default host gets a consistent ephemeral
+  // port, that is different from the other host's connection.
+
+  std::string other_server_name = "other.google.com";
+  EXPECT_NE(kDefaultServerHostName, other_server_name);
+  HostPortPair host_port_pair2(other_server_name, kDefaultServerPort);
+
+  int original_port = GetSourcePortForNewSession(host_port_pair_);
+  EXPECT_NE(original_port, GetSourcePortForNewSession(host_port_pair2));
+  EXPECT_EQ(original_port, GetSourcePortForNewSession(host_port_pair_));
+}
+
+TEST_P(QuicStreamFactoryTest, GoAwayDisablesConsistentEphemeralPort) {
+  // Get a session to the host using the port suggester.
+  int original_port =
+      GetSourcePortForNewSessionAndGoAway(host_port_pair_);
+  // Verify that the port is different after the goaway.
+  EXPECT_NE(original_port, GetSourcePortForNewSession(host_port_pair_));
+  // Since the previous session did not goaway we should see the original port.
+  EXPECT_EQ(original_port, GetSourcePortForNewSession(host_port_pair_));
+}
+
+TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
+  MockRead reads[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  scoped_ptr<QuicEncryptedPacket> rst(ConstructRstPacket());
+  std::vector<MockWrite> writes;
+  writes.push_back(MockWrite(ASYNC, rst->data(), rst->length(), 1));
+  DeterministicSocketData socket_data(reads, arraysize(reads),
+                                      writes.empty() ? nullptr  : &writes[0],
+                                      writes.size());
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  MockRead reads2[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  DeterministicSocketData socket_data2(reads2, arraysize(reads2), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data2.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  HttpRequestInfo request_info;
+  EXPECT_EQ(OK, stream->InitializeStream(&request_info,
+                                         DEFAULT_PRIORITY,
+                                         net_log_, CompletionCallback()));
+
+  // Close the session and verify that stream saw the error.
+  factory_.CloseAllSessions(ERR_INTERNET_DISCONNECTED);
+  EXPECT_EQ(ERR_INTERNET_DISCONNECTED,
+            stream->ReadResponseHeaders(callback_.callback()));
+
+  // Now attempting to request a stream to the same origin should create
+  // a new session.
+
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  stream = request2.ReleaseStream();
+  stream.reset();  // Will reset stream 3.
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, OnIPAddressChanged) {
+  MockRead reads[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  scoped_ptr<QuicEncryptedPacket> rst(ConstructRstPacket());
+  std::vector<MockWrite> writes;
+  writes.push_back(MockWrite(ASYNC, rst->data(), rst->length(), 1));
+  DeterministicSocketData socket_data(reads, arraysize(reads),
+                                      writes.empty() ? nullptr  : &writes[0],
+                                      writes.size());
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  MockRead reads2[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  DeterministicSocketData socket_data2(reads2, arraysize(reads2), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data2.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  HttpRequestInfo request_info;
+  EXPECT_EQ(OK, stream->InitializeStream(&request_info,
+                                         DEFAULT_PRIORITY,
+                                         net_log_, CompletionCallback()));
+
+  // Change the IP address and verify that stream saw the error.
+  factory_.OnIPAddressChanged();
+  EXPECT_EQ(ERR_NETWORK_CHANGED,
+            stream->ReadResponseHeaders(callback_.callback()));
+  EXPECT_TRUE(factory_.require_confirmation());
+
+  // Now attempting to request a stream to the same origin should create
+  // a new session.
+
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  stream = request2.ReleaseStream();
+  stream.reset();  // Will reset stream 3.
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, OnCertAdded) {
+  MockRead reads[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  scoped_ptr<QuicEncryptedPacket> rst(ConstructRstPacket());
+  std::vector<MockWrite> writes;
+  writes.push_back(MockWrite(ASYNC, rst->data(), rst->length(), 1));
+  DeterministicSocketData socket_data(reads, arraysize(reads),
+                                      writes.empty() ? nullptr  : &writes[0],
+                                      writes.size());
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  MockRead reads2[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  DeterministicSocketData socket_data2(reads2, arraysize(reads2), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data2.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  HttpRequestInfo request_info;
+  EXPECT_EQ(OK, stream->InitializeStream(&request_info,
+                                         DEFAULT_PRIORITY,
+                                         net_log_, CompletionCallback()));
+
+  // Add a cert and verify that stream saw the event.
+  factory_.OnCertAdded(nullptr);
+  EXPECT_EQ(ERR_CERT_DATABASE_CHANGED,
+            stream->ReadResponseHeaders(callback_.callback()));
+  EXPECT_FALSE(factory_.require_confirmation());
+
+  // Now attempting to request a stream to the same origin should create
+  // a new session.
+
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  stream = request2.ReleaseStream();
+  stream.reset();  // Will reset stream 3.
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, OnCACertChanged) {
+  MockRead reads[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  scoped_ptr<QuicEncryptedPacket> rst(ConstructRstPacket());
+  std::vector<MockWrite> writes;
+  writes.push_back(MockWrite(ASYNC, rst->data(), rst->length(), 1));
+  DeterministicSocketData socket_data(reads, arraysize(reads),
+                                      writes.empty() ? nullptr  : &writes[0],
+                                      writes.size());
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  MockRead reads2[] = {
+    MockRead(ASYNC, 0, 0)  // EOF
+  };
+  DeterministicSocketData socket_data2(reads2, arraysize(reads2), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data2);
+  socket_data2.StopAfter(1);
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  HttpRequestInfo request_info;
+  EXPECT_EQ(OK, stream->InitializeStream(&request_info,
+                                         DEFAULT_PRIORITY,
+                                         net_log_, CompletionCallback()));
+
+  // Change the CA cert and verify that stream saw the event.
+  factory_.OnCACertChanged(nullptr);
+  EXPECT_EQ(ERR_CERT_DATABASE_CHANGED,
+            stream->ReadResponseHeaders(callback_.callback()));
+  EXPECT_FALSE(factory_.require_confirmation());
+
+  // Now attempting to request a stream to the same origin should create
+  // a new session.
+
+  QuicStreamRequest request2(&factory_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_,
+                             is_https_,
+                             privacy_mode_,
+                             "GET",
+                             net_log_,
+                             callback_.callback()));
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  stream = request2.ReleaseStream();
+  stream.reset();  // Will reset stream 3.
+
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+  EXPECT_TRUE(socket_data2.at_read_eof());
+  EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, SharedCryptoConfig) {
+  vector<string> cannoncial_suffixes;
+  cannoncial_suffixes.push_back(string(".c.youtube.com"));
+  cannoncial_suffixes.push_back(string(".googlevideo.com"));
+
+  for (unsigned i = 0; i < cannoncial_suffixes.size(); ++i) {
+    string r1_host_name("r1");
+    string r2_host_name("r2");
+    r1_host_name.append(cannoncial_suffixes[i]);
+    r2_host_name.append(cannoncial_suffixes[i]);
+
+    HostPortPair host_port_pair1(r1_host_name, 80);
+    QuicCryptoClientConfig* crypto_config =
+        QuicStreamFactoryPeer::GetCryptoConfig(&factory_);
+    QuicServerId server_id1(host_port_pair1, is_https_, privacy_mode_);
+    QuicCryptoClientConfig::CachedState* cached1 =
+        crypto_config->LookupOrCreate(server_id1);
+    EXPECT_FALSE(cached1->proof_valid());
+    EXPECT_TRUE(cached1->source_address_token().empty());
+
+    // Mutate the cached1 to have different data.
+    // TODO(rtenneti): mutate other members of CachedState.
+    cached1->set_source_address_token(r1_host_name);
+    cached1->SetProofValid();
+
+    HostPortPair host_port_pair2(r2_host_name, 80);
+    QuicServerId server_id2(host_port_pair2, is_https_, privacy_mode_);
+    QuicCryptoClientConfig::CachedState* cached2 =
+        crypto_config->LookupOrCreate(server_id2);
+    EXPECT_EQ(cached1->source_address_token(), cached2->source_address_token());
+    EXPECT_TRUE(cached2->proof_valid());
+  }
+}
+
+TEST_P(QuicStreamFactoryTest, CryptoConfigWhenProofIsInvalid) {
+  vector<string> cannoncial_suffixes;
+  cannoncial_suffixes.push_back(string(".c.youtube.com"));
+  cannoncial_suffixes.push_back(string(".googlevideo.com"));
+
+  for (unsigned i = 0; i < cannoncial_suffixes.size(); ++i) {
+    string r3_host_name("r3");
+    string r4_host_name("r4");
+    r3_host_name.append(cannoncial_suffixes[i]);
+    r4_host_name.append(cannoncial_suffixes[i]);
+
+    HostPortPair host_port_pair1(r3_host_name, 80);
+    QuicCryptoClientConfig* crypto_config =
+        QuicStreamFactoryPeer::GetCryptoConfig(&factory_);
+    QuicServerId server_id1(host_port_pair1, is_https_, privacy_mode_);
+    QuicCryptoClientConfig::CachedState* cached1 =
+        crypto_config->LookupOrCreate(server_id1);
+    EXPECT_FALSE(cached1->proof_valid());
+    EXPECT_TRUE(cached1->source_address_token().empty());
+
+    // Mutate the cached1 to have different data.
+    // TODO(rtenneti): mutate other members of CachedState.
+    cached1->set_source_address_token(r3_host_name);
+    cached1->SetProofInvalid();
+
+    HostPortPair host_port_pair2(r4_host_name, 80);
+    QuicServerId server_id2(host_port_pair2, is_https_, privacy_mode_);
+    QuicCryptoClientConfig::CachedState* cached2 =
+        crypto_config->LookupOrCreate(server_id2);
+    EXPECT_NE(cached1->source_address_token(), cached2->source_address_token());
+    EXPECT_TRUE(cached2->source_address_token().empty());
+    EXPECT_FALSE(cached2->proof_valid());
+  }
+}
+
+}  // namespace test
+}  // namespace net