xref: /aosp_15_r20/external/cronet/net/spdy/spdy_session_pool_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/spdy/spdy_session_pool.h"
6 
7 #include <cstddef>
8 #include <tuple>
9 #include <utility>
10 
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/run_loop.h"
16 #include "base/test/bind.h"
17 #include "base/test/metrics/histogram_tester.h"
18 #include "base/trace_event/memory_allocator_dump.h"
19 #include "base/trace_event/process_memory_dump.h"
20 #include "build/build_config.h"
21 #include "net/base/proxy_string_util.h"
22 #include "net/base/session_usage.h"
23 #include "net/base/test_completion_callback.h"
24 #include "net/base/tracing.h"
25 #include "net/dns/host_cache.h"
26 #include "net/dns/public/host_resolver_results.h"
27 #include "net/dns/public/secure_dns_policy.h"
28 #include "net/http/http_network_session.h"
29 #include "net/log/net_log_with_source.h"
30 #include "net/log/test_net_log.h"
31 #include "net/socket/client_socket_handle.h"
32 #include "net/socket/socket_tag.h"
33 #include "net/socket/socket_test_util.h"
34 #include "net/socket/transport_client_socket_pool.h"
35 #include "net/spdy/spdy_session.h"
36 #include "net/spdy/spdy_stream_test_util.h"
37 #include "net/spdy/spdy_test_util_common.h"
38 #include "net/test/cert_test_util.h"
39 #include "net/test/gtest_util.h"
40 #include "net/test/test_certificate_data.h"
41 #include "net/test/test_data_directory.h"
42 #include "net/test/test_with_task_environment.h"
43 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
44 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 
48 using base::trace_event::MemoryAllocatorDump;
49 using net::test::IsError;
50 using net::test::IsOk;
51 using testing::Contains;
52 using testing::Eq;
53 using testing::Contains;
54 using testing::ByRef;
55 
56 namespace net {
57 
58 class SpdySessionPoolTest : public TestWithTaskEnvironment {
59  protected:
60   // Used by RunIPPoolingTest().
61   enum SpdyPoolCloseSessionsType {
62     SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
63     SPDY_POOL_CLOSE_CURRENT_SESSIONS,
64     SPDY_POOL_CLOSE_IDLE_SESSIONS,
65   };
66 
67   SpdySessionPoolTest() = default;
68 
CreateNetworkSession()69   void CreateNetworkSession() {
70     http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
71     spdy_session_pool_ = http_session_->spdy_session_pool();
72   }
73 
AddSSLSocketData()74   void AddSSLSocketData() {
75     auto ssl = std::make_unique<SSLSocketDataProvider>(SYNCHRONOUS, OK);
76     ssl->ssl_info.cert =
77         ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
78     ASSERT_TRUE(ssl->ssl_info.cert);
79     session_deps_.socket_factory->AddSSLSocketDataProvider(ssl.get());
80     ssl_data_vector_.push_back(std::move(ssl));
81   }
82 
83   void RunIPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type);
84   void RunIPPoolingDisabledTest(SSLSocketDataProvider* ssl);
85 
num_active_streams(base::WeakPtr<SpdySession> session)86   size_t num_active_streams(base::WeakPtr<SpdySession> session) {
87     return session->active_streams_.size();
88   }
89 
max_concurrent_streams(base::WeakPtr<SpdySession> session)90   size_t max_concurrent_streams(base::WeakPtr<SpdySession> session) {
91     return session->max_concurrent_streams_;
92   }
93 
94   SpdySessionDependencies session_deps_;
95   std::unique_ptr<HttpNetworkSession> http_session_;
96   raw_ptr<SpdySessionPool, DanglingUntriaged> spdy_session_pool_ = nullptr;
97   std::vector<std::unique_ptr<SSLSocketDataProvider>> ssl_data_vector_;
98 };
99 
100 class SpdySessionRequestDelegate
101     : public SpdySessionPool::SpdySessionRequest::Delegate {
102  public:
103   SpdySessionRequestDelegate() = default;
104 
105   SpdySessionRequestDelegate(const SpdySessionRequestDelegate&) = delete;
106   SpdySessionRequestDelegate& operator=(const SpdySessionRequestDelegate&) =
107       delete;
108 
109   ~SpdySessionRequestDelegate() override = default;
110 
OnSpdySessionAvailable(base::WeakPtr<SpdySession> spdy_session)111   void OnSpdySessionAvailable(
112       base::WeakPtr<SpdySession> spdy_session) override {
113     EXPECT_FALSE(callback_invoked_);
114     callback_invoked_ = true;
115     spdy_session_ = spdy_session;
116   }
117 
callback_invoked() const118   bool callback_invoked() const { return callback_invoked_; }
119 
spdy_session()120   SpdySession* spdy_session() { return spdy_session_.get(); }
121 
122  private:
123   bool callback_invoked_ = false;
124   base::WeakPtr<SpdySession> spdy_session_;
125 };
126 
127 // Attempts to set up an alias for |key| using an already existing session in
128 // |pool|. To do this, simulates a host resolution that returns
129 // |endpoints|.
TryCreateAliasedSpdySession(SpdySessionPool * pool,const SpdySessionKey & key,const std::vector<HostResolverEndpointResult> & endpoints,bool enable_ip_based_pooling=true,bool is_websocket=false)130 bool TryCreateAliasedSpdySession(
131     SpdySessionPool* pool,
132     const SpdySessionKey& key,
133     const std::vector<HostResolverEndpointResult>& endpoints,
134     bool enable_ip_based_pooling = true,
135     bool is_websocket = false) {
136   // The requested session must not already exist.
137   EXPECT_FALSE(pool->FindAvailableSession(key, enable_ip_based_pooling,
138                                           is_websocket, NetLogWithSource()));
139 
140   // Create a request for the session. There should be no matching session
141   // (aliased or otherwise) yet. A pending request is necessary for the session
142   // to create an alias on host resolution completion.
143   std::unique_ptr<SpdySessionPool::SpdySessionRequest> request;
144   bool is_blocking_request_for_session = false;
145   SpdySessionRequestDelegate request_delegate;
146   EXPECT_FALSE(pool->RequestSession(
147       key, enable_ip_based_pooling, is_websocket, NetLogWithSource(),
148       /* on_blocking_request_destroyed_callback = */ base::RepeatingClosure(),
149       &request_delegate, &request, &is_blocking_request_for_session));
150   EXPECT_TRUE(request);
151   EXPECT_TRUE(is_blocking_request_for_session);
152 
153   // Simulate a host resolution completing.
154   OnHostResolutionCallbackResult result = pool->OnHostResolutionComplete(
155       key, is_websocket, endpoints, /*aliases=*/{});
156 
157   // Spin the message loop and see if it creates an H2 session.
158   base::RunLoop().RunUntilIdle();
159   EXPECT_EQ(request_delegate.callback_invoked(),
160             result == OnHostResolutionCallbackResult::kMayBeDeletedAsync);
161   EXPECT_EQ(request_delegate.callback_invoked(),
162             request_delegate.spdy_session() != nullptr);
163   request.reset();
164 
165   // Calling RequestSession again should return request_delegate.spdy_session()
166   // (i.e. the newly created session, if a session was created, or nullptr, if
167   // one was not.)
168   EXPECT_EQ(request_delegate.spdy_session(),
169             pool->RequestSession(key, enable_ip_based_pooling, is_websocket,
170                                  NetLogWithSource(),
171                                  /* on_blocking_request_destroyed_callback = */
172                                  base::RepeatingClosure(), &request_delegate,
173                                  &request, &is_blocking_request_for_session)
174                 .get());
175 
176   return request_delegate.spdy_session() != nullptr;
177 }
178 
179 // Attempts to set up an alias for |key| using an already existing session in
180 // |pool|. To do this, simulates a host resolution that returns
181 // |ip_address_list|.
TryCreateAliasedSpdySession(SpdySessionPool * pool,const SpdySessionKey & key,const std::string & ip_address_list,bool enable_ip_based_pooling=true,bool is_websocket=false)182 bool TryCreateAliasedSpdySession(SpdySessionPool* pool,
183                                  const SpdySessionKey& key,
184                                  const std::string& ip_address_list,
185                                  bool enable_ip_based_pooling = true,
186                                  bool is_websocket = false) {
187   std::vector<IPEndPoint> ip_endpoints;
188   EXPECT_THAT(ParseAddressList(ip_address_list, &ip_endpoints), IsOk());
189   HostResolverEndpointResult endpoint;
190   for (auto& ip_endpoint : ip_endpoints) {
191     endpoint.ip_endpoints.emplace_back(ip_endpoint.address(), 443);
192   }
193   return TryCreateAliasedSpdySession(pool, key, {endpoint},
194                                      enable_ip_based_pooling, is_websocket);
195 }
196 
197 // A delegate that opens a new session when it is closed.
198 class SessionOpeningDelegate : public SpdyStream::Delegate {
199  public:
SessionOpeningDelegate(SpdySessionPool * spdy_session_pool,const SpdySessionKey & key)200   SessionOpeningDelegate(SpdySessionPool* spdy_session_pool,
201                          const SpdySessionKey& key)
202       : spdy_session_pool_(spdy_session_pool),
203         key_(key) {}
204 
205   ~SessionOpeningDelegate() override = default;
206 
OnHeadersSent()207   void OnHeadersSent() override {}
208 
OnEarlyHintsReceived(const spdy::Http2HeaderBlock & headers)209   void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override {}
210 
OnHeadersReceived(const spdy::Http2HeaderBlock & response_headers)211   void OnHeadersReceived(
212       const spdy::Http2HeaderBlock& response_headers) override {}
213 
OnDataReceived(std::unique_ptr<SpdyBuffer> buffer)214   void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override {}
215 
OnDataSent()216   void OnDataSent() override {}
217 
OnTrailers(const spdy::Http2HeaderBlock & trailers)218   void OnTrailers(const spdy::Http2HeaderBlock& trailers) override {}
219 
OnClose(int status)220   void OnClose(int status) override {
221     std::ignore = CreateFakeSpdySession(spdy_session_pool_, key_);
222   }
223 
CanGreaseFrameType() const224   bool CanGreaseFrameType() const override { return false; }
225 
source_dependency() const226   NetLogSource source_dependency() const override { return NetLogSource(); }
227 
228  private:
229   const raw_ptr<SpdySessionPool> spdy_session_pool_;
230   const SpdySessionKey key_;
231 };
232 
233 // Set up a SpdyStream to create a new session when it is closed.
234 // CloseCurrentSessions should not close the newly-created session.
TEST_F(SpdySessionPoolTest,CloseCurrentSessions)235 TEST_F(SpdySessionPoolTest, CloseCurrentSessions) {
236   const char kTestHost[] = "www.foo.com";
237   const int kTestPort = 80;
238 
239   HostPortPair test_host_port_pair(kTestHost, kTestPort);
240   SpdySessionKey test_key = SpdySessionKey(
241       test_host_port_pair, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
242       SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
243       SecureDnsPolicy::kAllow,
244       /*disable_cert_verification_network_fetches=*/false);
245 
246   MockConnect connect_data(SYNCHRONOUS, OK);
247   MockRead reads[] = {
248     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
249   };
250 
251   StaticSocketDataProvider data(reads, base::span<MockWrite>());
252   data.set_connect_data(connect_data);
253   session_deps_.socket_factory->AddSocketDataProvider(&data);
254 
255   SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
256   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
257 
258   CreateNetworkSession();
259 
260   // Setup the first session to the first host.
261   base::WeakPtr<SpdySession> session =
262       CreateSpdySession(http_session_.get(), test_key, NetLogWithSource());
263 
264   // Flush the SpdySession::OnReadComplete() task.
265   base::RunLoop().RunUntilIdle();
266 
267   // Verify that we have sessions for everything.
268   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
269 
270   // Set the stream to create a new session when it is closed.
271   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
272       SPDY_BIDIRECTIONAL_STREAM, session, GURL("http://www.foo.com"), MEDIUM,
273       NetLogWithSource());
274   SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
275   spdy_stream->SetDelegate(&delegate);
276 
277   // Close the current session.
278   spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
279 
280   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
281 }
282 
TEST_F(SpdySessionPoolTest,CloseCurrentIdleSessions)283 TEST_F(SpdySessionPoolTest, CloseCurrentIdleSessions) {
284   const std::string close_session_description = "Closing idle sessions.";
285   MockConnect connect_data(SYNCHRONOUS, OK);
286   MockRead reads[] = {
287       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
288   };
289 
290   StaticSocketDataProvider data1(reads, base::span<MockWrite>());
291   data1.set_connect_data(connect_data);
292   session_deps_.socket_factory->AddSocketDataProvider(&data1);
293 
294   AddSSLSocketData();
295   AddSSLSocketData();
296   AddSSLSocketData();
297 
298   CreateNetworkSession();
299 
300   // Set up session 1
301   const GURL url1("https://www.example.org");
302   HostPortPair test_host_port_pair1(HostPortPair::FromURL(url1));
303   SpdySessionKey key1(test_host_port_pair1, PRIVACY_MODE_DISABLED,
304                       ProxyChain::Direct(), SessionUsage::kDestination,
305                       SocketTag(), NetworkAnonymizationKey(),
306                       SecureDnsPolicy::kAllow,
307                       /*disable_cert_verification_network_fetches=*/false);
308   base::WeakPtr<SpdySession> session1 =
309       CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
310   base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
311       SPDY_BIDIRECTIONAL_STREAM, session1, url1, MEDIUM, NetLogWithSource());
312   ASSERT_TRUE(spdy_stream1);
313 
314   // Set up session 2
315   StaticSocketDataProvider data2(reads, base::span<MockWrite>());
316   session_deps_.socket_factory->AddSocketDataProvider(&data2);
317   const GURL url2("https://mail.example.org");
318   HostPortPair test_host_port_pair2(HostPortPair::FromURL(url2));
319   SpdySessionKey key2(test_host_port_pair2, PRIVACY_MODE_DISABLED,
320                       ProxyChain::Direct(), SessionUsage::kDestination,
321                       SocketTag(), NetworkAnonymizationKey(),
322                       SecureDnsPolicy::kAllow,
323                       /*disable_cert_verification_network_fetches=*/false);
324   base::WeakPtr<SpdySession> session2 =
325       CreateSpdySession(http_session_.get(), key2, NetLogWithSource());
326   base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
327       SPDY_BIDIRECTIONAL_STREAM, session2, url2, MEDIUM, NetLogWithSource());
328   ASSERT_TRUE(spdy_stream2);
329 
330   // Set up session 3
331   StaticSocketDataProvider data3(reads, base::span<MockWrite>());
332   data3.set_connect_data(connect_data);
333   session_deps_.socket_factory->AddSocketDataProvider(&data3);
334   const GURL url3("https://mail.example.com");
335   HostPortPair test_host_port_pair3(HostPortPair::FromURL(url3));
336   SpdySessionKey key3(test_host_port_pair3, PRIVACY_MODE_DISABLED,
337                       ProxyChain::Direct(), SessionUsage::kDestination,
338                       SocketTag(), NetworkAnonymizationKey(),
339                       SecureDnsPolicy::kAllow,
340                       /*disable_cert_verification_network_fetches=*/false);
341   base::WeakPtr<SpdySession> session3 =
342       CreateSpdySession(http_session_.get(), key3, NetLogWithSource());
343   base::WeakPtr<SpdyStream> spdy_stream3 = CreateStreamSynchronously(
344       SPDY_BIDIRECTIONAL_STREAM, session3, url3, MEDIUM, NetLogWithSource());
345   ASSERT_TRUE(spdy_stream3);
346 
347   // All sessions are active and not closed
348   EXPECT_TRUE(session1->is_active());
349   EXPECT_TRUE(session1->IsAvailable());
350   EXPECT_TRUE(session2->is_active());
351   EXPECT_TRUE(session2->IsAvailable());
352   EXPECT_TRUE(session3->is_active());
353   EXPECT_TRUE(session3->IsAvailable());
354 
355   // Should not do anything, all are active
356   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
357   EXPECT_TRUE(session1->is_active());
358   EXPECT_TRUE(session1->IsAvailable());
359   EXPECT_TRUE(session2->is_active());
360   EXPECT_TRUE(session2->IsAvailable());
361   EXPECT_TRUE(session3->is_active());
362   EXPECT_TRUE(session3->IsAvailable());
363 
364   // Make sessions 1 and 3 inactive, but keep them open.
365   // Session 2 still open and active
366   session1->CloseCreatedStream(spdy_stream1, OK);
367   EXPECT_FALSE(spdy_stream1);
368   session3->CloseCreatedStream(spdy_stream3, OK);
369   EXPECT_FALSE(spdy_stream3);
370   EXPECT_FALSE(session1->is_active());
371   EXPECT_TRUE(session1->IsAvailable());
372   EXPECT_TRUE(session2->is_active());
373   EXPECT_TRUE(session2->IsAvailable());
374   EXPECT_FALSE(session3->is_active());
375   EXPECT_TRUE(session3->IsAvailable());
376 
377   // Should close session 1 and 3, 2 should be left open
378   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
379   base::RunLoop().RunUntilIdle();
380 
381   EXPECT_FALSE(session1);
382   EXPECT_TRUE(session2->is_active());
383   EXPECT_TRUE(session2->IsAvailable());
384   EXPECT_FALSE(session3);
385 
386   // Should not do anything
387   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
388   base::RunLoop().RunUntilIdle();
389 
390   EXPECT_TRUE(session2->is_active());
391   EXPECT_TRUE(session2->IsAvailable());
392 
393   // Make 2 not active
394   session2->CloseCreatedStream(spdy_stream2, OK);
395   base::RunLoop().RunUntilIdle();
396 
397   EXPECT_FALSE(spdy_stream2);
398   EXPECT_FALSE(session2->is_active());
399   EXPECT_TRUE(session2->IsAvailable());
400 
401   // This should close session 2
402   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
403   base::RunLoop().RunUntilIdle();
404 
405   EXPECT_FALSE(session2);
406 }
407 
408 // Set up a SpdyStream to create a new session when it is closed.
409 // CloseAllSessions should close the newly-created session.
TEST_F(SpdySessionPoolTest,CloseAllSessions)410 TEST_F(SpdySessionPoolTest, CloseAllSessions) {
411   const char kTestHost[] = "www.foo.com";
412   const int kTestPort = 80;
413 
414   HostPortPair test_host_port_pair(kTestHost, kTestPort);
415   SpdySessionKey test_key = SpdySessionKey(
416       test_host_port_pair, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
417       SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
418       SecureDnsPolicy::kAllow,
419       /*disable_cert_verification_network_fetches=*/false);
420 
421   MockConnect connect_data(SYNCHRONOUS, OK);
422   MockRead reads[] = {
423     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
424   };
425 
426   StaticSocketDataProvider data(reads, base::span<MockWrite>());
427   data.set_connect_data(connect_data);
428   session_deps_.socket_factory->AddSocketDataProvider(&data);
429 
430   SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
431   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
432 
433   CreateNetworkSession();
434 
435   // Setup the first session to the first host.
436   base::WeakPtr<SpdySession> session =
437       CreateSpdySession(http_session_.get(), test_key, NetLogWithSource());
438 
439   // Flush the SpdySession::OnReadComplete() task.
440   base::RunLoop().RunUntilIdle();
441 
442   // Verify that we have sessions for everything.
443   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
444 
445   // Set the stream to create a new session when it is closed.
446   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
447       SPDY_BIDIRECTIONAL_STREAM, session, GURL("http://www.foo.com"), MEDIUM,
448       NetLogWithSource());
449   SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
450   spdy_stream->SetDelegate(&delegate);
451 
452   // Close the current session.
453   spdy_session_pool_->CloseAllSessions();
454 
455   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key));
456 }
457 
458 // Code testing SpdySessionPool::OnIPAddressChange requires a SpdySessionPool
459 // with some active sessions. This fixture takes care of setting most things up
460 // but doesn't create the pool yet, allowing tests to possibly further
461 // configure sessions_deps_.
462 class SpdySessionPoolOnIPAddressChangeTest : public SpdySessionPoolTest {
463  protected:
SpdySessionPoolOnIPAddressChangeTest()464   SpdySessionPoolOnIPAddressChangeTest()
465       : test_host_port_pair_(kTestHost, kTestPort),
466         reads_({
467             MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
468         }),
469         test_key_(SpdySessionKey(
470             test_host_port_pair_,
471             PRIVACY_MODE_DISABLED,
472             ProxyChain::Direct(),
473             SessionUsage::kDestination,
474             SocketTag(),
475             NetworkAnonymizationKey(),
476             SecureDnsPolicy::kAllow,
477             /*disable_cert_verification_network_fetches=*/false)),
478         connect_data_(SYNCHRONOUS, OK),
479         data_(reads_, base::span<MockWrite>()),
480         ssl_(SYNCHRONOUS, OK) {
481     data_.set_connect_data(connect_data_);
482     session_deps_.socket_factory->AddSocketDataProvider(&data_);
483     session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
484   }
485 
486   static constexpr char kTestHost[] = "www.foo.com";
487   static constexpr int kTestPort = 80;
488   static constexpr int kReadSize = 1;
489 
490   const HostPortPair test_host_port_pair_;
491   const std::array<MockRead, kReadSize> reads_;
492   const SpdySessionKey test_key_;
493   const MockConnect connect_data_;
494   StaticSocketDataProvider data_;
495   SSLSocketDataProvider ssl_;
496 };
497 
TEST_F(SpdySessionPoolOnIPAddressChangeTest,DoNotIgnoreIPAddressChanges)498 TEST_F(SpdySessionPoolOnIPAddressChangeTest, DoNotIgnoreIPAddressChanges) {
499   // Default behavior should be ignore_ip_address_changes = false;
500   CreateNetworkSession();
501 
502   base::WeakPtr<SpdySession> session =
503       CreateSpdySession(http_session_.get(), test_key_, NetLogWithSource());
504 
505   // Flush the SpdySession::OnReadComplete() task.
506   base::RunLoop().RunUntilIdle();
507   // Verify that we have a session.
508   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key_));
509 
510   // Without setting session_deps_.ignore_ip_address_changes = true the pool
511   // should close (or make unavailable) all sessions after an IP address change.
512   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
513   base::RunLoop().RunUntilIdle();
514   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key_));
515 }
516 
TEST_F(SpdySessionPoolOnIPAddressChangeTest,IgnoreIPAddressChanges)517 TEST_F(SpdySessionPoolOnIPAddressChangeTest, IgnoreIPAddressChanges) {
518   session_deps_.ignore_ip_address_changes = true;
519   CreateNetworkSession();
520 
521   // Setup the first session to the first host.
522   base::WeakPtr<SpdySession> session =
523       CreateSpdySession(http_session_.get(), test_key_, NetLogWithSource());
524   // Flush the SpdySession::OnReadComplete() task.
525   base::RunLoop().RunUntilIdle();
526   // Verify that we have a session.
527   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key_));
528 
529   // Since we set ignore_ip_address_changes = true, the session should still be
530   // there after an IP address change.
531   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
532   base::RunLoop().RunUntilIdle();
533   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key_));
534 }
535 
536 // This test has three variants, one for each style of closing the connection.
537 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
538 // the sessions are closed manually, calling SpdySessionPool::Remove() directly.
539 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS,
540 // sessions are closed with SpdySessionPool::CloseCurrentSessions().
541 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS,
542 // sessions are closed with SpdySessionPool::CloseIdleSessions().
RunIPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type)543 void SpdySessionPoolTest::RunIPPoolingTest(
544     SpdyPoolCloseSessionsType close_sessions_type) {
545   constexpr int kTestPort = 443;
546   struct TestHosts {
547     std::string url;
548     std::string name;
549     std::string iplist;
550     SpdySessionKey key;
551   } test_hosts[] = {
552       {"http://www.example.org", "www.example.org",
553        "192.0.2.33,192.168.0.1,192.168.0.5"},
554       {"http://mail.example.org", "mail.example.org",
555        "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33"},
556       {"http://mail.example.com", "mail.example.com",
557        "192.168.0.4,192.168.0.3"},
558   };
559 
560   for (auto& test_host : test_hosts) {
561     session_deps_.host_resolver->rules()->AddIPLiteralRule(
562         test_host.name, test_host.iplist, std::string());
563 
564     test_host.key = SpdySessionKey(
565         HostPortPair(test_host.name, kTestPort), PRIVACY_MODE_DISABLED,
566         ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
567         NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
568         /*disable_cert_verification_network_fetches=*/false);
569   }
570 
571   MockConnect connect_data(SYNCHRONOUS, OK);
572   MockRead reads[] = {
573     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
574   };
575 
576   StaticSocketDataProvider data1(reads, base::span<MockWrite>());
577   data1.set_connect_data(connect_data);
578   session_deps_.socket_factory->AddSocketDataProvider(&data1);
579 
580   AddSSLSocketData();
581 
582   CreateNetworkSession();
583 
584   // Setup the first session to the first host.
585   base::WeakPtr<SpdySession> session = CreateSpdySession(
586       http_session_.get(), test_hosts[0].key, NetLogWithSource());
587 
588   // Flush the SpdySession::OnReadComplete() task.
589   base::RunLoop().RunUntilIdle();
590 
591   // The third host has no overlap with the first, so it can't pool IPs.
592   EXPECT_FALSE(TryCreateAliasedSpdySession(
593       spdy_session_pool_, test_hosts[2].key, test_hosts[2].iplist));
594 
595   // The second host overlaps with the first, and should IP pool.
596   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
597                                           test_hosts[1].iplist));
598 
599   // However, if IP pooling is disabled, FindAvailableSession() should not find
600   // |session| for the second host.
601   base::WeakPtr<SpdySession> session1 =
602       spdy_session_pool_->FindAvailableSession(
603           test_hosts[1].key, /* enable_ip_based_pooling = */ false,
604           /* is_websocket = */ false, NetLogWithSource());
605   EXPECT_FALSE(session1);
606 
607   // Verify that the second host, through a proxy, won't share the IP, even if
608   // the IP list matches.
609   SpdySessionKey proxy_key(
610       test_hosts[1].key.host_port_pair(), PRIVACY_MODE_DISABLED,
611       PacResultElementToProxyChain("HTTP http://proxy.foo.com/"),
612       SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
613       SecureDnsPolicy::kAllow,
614       /*disable_cert_verification_network_fetches=*/false);
615   EXPECT_FALSE(TryCreateAliasedSpdySession(spdy_session_pool_, proxy_key,
616                                            test_hosts[1].iplist));
617 
618   // Verify that the second host, with a different SecureDnsPolicy,
619   // won't share the IP, even if the IP list matches.
620   SpdySessionKey disable_secure_dns_key(
621       test_hosts[1].key.host_port_pair(), PRIVACY_MODE_DISABLED,
622       ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
623       NetworkAnonymizationKey(), SecureDnsPolicy::kDisable,
624       /*disable_cert_verification_network_fetches=*/false);
625   EXPECT_FALSE(TryCreateAliasedSpdySession(
626       spdy_session_pool_, disable_secure_dns_key, test_hosts[1].iplist));
627 
628   // Overlap between 2 and 3 is not transitive to 1.
629   EXPECT_FALSE(TryCreateAliasedSpdySession(
630       spdy_session_pool_, test_hosts[2].key, test_hosts[2].iplist));
631 
632   // Create a new session to host 2.
633   StaticSocketDataProvider data2(reads, base::span<MockWrite>());
634   data2.set_connect_data(connect_data);
635   session_deps_.socket_factory->AddSocketDataProvider(&data2);
636 
637   AddSSLSocketData();
638 
639   base::WeakPtr<SpdySession> session2 = CreateSpdySession(
640       http_session_.get(), test_hosts[2].key, NetLogWithSource());
641 
642   // Verify that we have sessions for everything.
643   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
644   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
645   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
646 
647   // Grab the session to host 1 and verify that it is the same session
648   // we got with host 0, and that is a different from host 2's session.
649   session1 = spdy_session_pool_->FindAvailableSession(
650       test_hosts[1].key, /* enable_ip_based_pooling = */ true,
651       /* is_websocket = */ false, NetLogWithSource());
652   EXPECT_EQ(session.get(), session1.get());
653   EXPECT_NE(session2.get(), session1.get());
654 
655   // Remove the aliases and observe that we still have a session for host1.
656   SpdySessionPoolPeer pool_peer(spdy_session_pool_);
657   pool_peer.RemoveAliases(test_hosts[0].key);
658   pool_peer.RemoveAliases(test_hosts[1].key);
659   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
660 
661   // Cleanup the sessions.
662   switch (close_sessions_type) {
663     case SPDY_POOL_CLOSE_SESSIONS_MANUALLY:
664       session->CloseSessionOnError(ERR_ABORTED, std::string());
665       session2->CloseSessionOnError(ERR_ABORTED, std::string());
666       base::RunLoop().RunUntilIdle();
667       EXPECT_FALSE(session);
668       EXPECT_FALSE(session2);
669       break;
670     case SPDY_POOL_CLOSE_CURRENT_SESSIONS:
671       spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
672       break;
673     case SPDY_POOL_CLOSE_IDLE_SESSIONS:
674       GURL url(test_hosts[0].url);
675       base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
676           SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, NetLogWithSource());
677       GURL url1(test_hosts[1].url);
678       base::WeakPtr<SpdyStream> spdy_stream1 =
679           CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session1, url1,
680                                     MEDIUM, NetLogWithSource());
681       GURL url2(test_hosts[2].url);
682       base::WeakPtr<SpdyStream> spdy_stream2 =
683           CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session2, url2,
684                                     MEDIUM, NetLogWithSource());
685 
686       // Close streams to make spdy_session and spdy_session1 inactive.
687       session->CloseCreatedStream(spdy_stream, OK);
688       EXPECT_FALSE(spdy_stream);
689       session1->CloseCreatedStream(spdy_stream1, OK);
690       EXPECT_FALSE(spdy_stream1);
691 
692       // Check spdy_session and spdy_session1 are not closed.
693       EXPECT_FALSE(session->is_active());
694       EXPECT_TRUE(session->IsAvailable());
695       EXPECT_FALSE(session1->is_active());
696       EXPECT_TRUE(session1->IsAvailable());
697       EXPECT_TRUE(session2->is_active());
698       EXPECT_TRUE(session2->IsAvailable());
699 
700       // Test that calling CloseIdleSessions, does not cause a crash.
701       // http://crbug.com/181400
702       spdy_session_pool_->CloseCurrentIdleSessions("Closing idle sessions.");
703       base::RunLoop().RunUntilIdle();
704 
705       // Verify spdy_session and spdy_session1 are closed.
706       EXPECT_FALSE(session);
707       EXPECT_FALSE(session1);
708       EXPECT_TRUE(session2->is_active());
709       EXPECT_TRUE(session2->IsAvailable());
710 
711       spdy_stream2->Cancel(ERR_ABORTED);
712       EXPECT_FALSE(spdy_stream);
713       EXPECT_FALSE(spdy_stream1);
714       EXPECT_FALSE(spdy_stream2);
715 
716       session2->CloseSessionOnError(ERR_ABORTED, std::string());
717       base::RunLoop().RunUntilIdle();
718       EXPECT_FALSE(session2);
719       break;
720   }
721 
722   // Verify that the map is all cleaned up.
723   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
724   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
725   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
726   EXPECT_FALSE(TryCreateAliasedSpdySession(
727       spdy_session_pool_, test_hosts[0].key, test_hosts[0].iplist));
728   EXPECT_FALSE(TryCreateAliasedSpdySession(
729       spdy_session_pool_, test_hosts[1].key, test_hosts[1].iplist));
730   EXPECT_FALSE(TryCreateAliasedSpdySession(
731       spdy_session_pool_, test_hosts[2].key, test_hosts[2].iplist));
732 }
733 
RunIPPoolingDisabledTest(SSLSocketDataProvider * ssl)734 void SpdySessionPoolTest::RunIPPoolingDisabledTest(SSLSocketDataProvider* ssl) {
735   constexpr int kTestPort = 443;
736   struct TestHosts {
737     std::string name;
738     std::string iplist;
739     SpdySessionKey key;
740   } test_hosts[] = {
741       {"www.webkit.org", "192.0.2.33,192.168.0.1,192.168.0.5"},
742       {"js.webkit.com", "192.168.0.4,192.168.0.1,192.0.2.33"},
743   };
744 
745   session_deps_.host_resolver->set_synchronous_mode(true);
746   for (auto& test_host : test_hosts) {
747     session_deps_.host_resolver->rules()->AddIPLiteralRule(
748         test_host.name, test_host.iplist, std::string());
749 
750     // Setup a SpdySessionKey
751     test_host.key = SpdySessionKey(
752         HostPortPair(test_host.name, kTestPort), PRIVACY_MODE_DISABLED,
753         ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
754         NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
755         /*disable_cert_verification_network_fetches=*/false);
756   }
757 
758   MockRead reads[] = {
759       MockRead(ASYNC, ERR_IO_PENDING),
760   };
761   StaticSocketDataProvider data(reads, base::span<MockWrite>());
762   session_deps_.socket_factory->AddSocketDataProvider(&data);
763   session_deps_.socket_factory->AddSSLSocketDataProvider(ssl);
764 
765   CreateNetworkSession();
766 
767   base::WeakPtr<SpdySession> spdy_session = CreateSpdySession(
768       http_session_.get(), test_hosts[0].key, NetLogWithSource());
769   EXPECT_TRUE(
770       HasSpdySession(http_session_->spdy_session_pool(), test_hosts[0].key));
771   EXPECT_FALSE(TryCreateAliasedSpdySession(
772       spdy_session_pool_, test_hosts[1].key, test_hosts[1].iplist,
773       /* enable_ip_based_pooling = */ false));
774 
775   http_session_->spdy_session_pool()->CloseAllSessions();
776 }
777 
TEST_F(SpdySessionPoolTest,IPPooling)778 TEST_F(SpdySessionPoolTest, IPPooling) {
779   RunIPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY);
780 }
781 
TEST_F(SpdySessionPoolTest,IPPoolingCloseCurrentSessions)782 TEST_F(SpdySessionPoolTest, IPPoolingCloseCurrentSessions) {
783   RunIPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS);
784 }
785 
TEST_F(SpdySessionPoolTest,IPPoolingCloseIdleSessions)786 TEST_F(SpdySessionPoolTest, IPPoolingCloseIdleSessions) {
787   RunIPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS);
788 }
789 
790 // Regression test for https://crbug.com/643025.
TEST_F(SpdySessionPoolTest,IPPoolingNetLog)791 TEST_F(SpdySessionPoolTest, IPPoolingNetLog) {
792   // Define two hosts with identical IP address.
793   constexpr int kTestPort = 443;
794   struct TestHosts {
795     std::string name;
796     std::string iplist;
797     SpdySessionKey key;
798   } test_hosts[] = {
799       {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"},
800   };
801 
802   // Populate the HostResolver cache.
803   session_deps_.host_resolver->set_synchronous_mode(true);
804   for (auto& test_host : test_hosts) {
805     session_deps_.host_resolver->rules()->AddIPLiteralRule(
806         test_host.name, test_host.iplist, std::string());
807 
808     test_host.key = SpdySessionKey(
809         HostPortPair(test_host.name, kTestPort), PRIVACY_MODE_DISABLED,
810         ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
811         NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
812         /*disable_cert_verification_network_fetches=*/false);
813   }
814 
815   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
816   StaticSocketDataProvider data(reads, base::span<MockWrite>());
817   MockConnect connect_data(SYNCHRONOUS, OK);
818   data.set_connect_data(connect_data);
819 
820   session_deps_.socket_factory->AddSocketDataProvider(&data);
821   AddSSLSocketData();
822 
823   CreateNetworkSession();
824 
825   // Open SpdySession to the first host.
826   base::WeakPtr<SpdySession> session0 = CreateSpdySession(
827       http_session_.get(), test_hosts[0].key, NetLogWithSource());
828 
829   // The second host should pool to the existing connection.
830   RecordingNetLogObserver net_log_observer;
831   base::HistogramTester histogram_tester;
832   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
833                                           test_hosts[1].iplist));
834   histogram_tester.ExpectTotalCount("Net.SpdySessionGet", 1);
835 
836   base::WeakPtr<SpdySession> session1 =
837       spdy_session_pool_->FindAvailableSession(
838           test_hosts[1].key, /* enable_ip_based_pooling = */ true,
839           /* is_websocket = */ false,
840           NetLogWithSource::Make(NetLogSourceType::NONE));
841   EXPECT_EQ(session0.get(), session1.get());
842 
843   ASSERT_EQ(1u, net_log_observer.GetSize());
844   histogram_tester.ExpectTotalCount("Net.SpdySessionGet", 2);
845 
846   // FindAvailableSession() should have logged a netlog event indicating IP
847   // pooling.
848   auto entry_list = net_log_observer.GetEntries();
849   EXPECT_EQ(
850       NetLogEventType::HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL,
851       entry_list[0].type);
852 
853   // Both FindAvailableSession() calls (including one from
854   // TryCreateAliasedSpdySession) should log histogram entries indicating IP
855   // pooling.
856   histogram_tester.ExpectUniqueSample("Net.SpdySessionGet", 2, 2);
857 }
858 
859 // Test IP pooling when the DNS responses have ALPNs.
TEST_F(SpdySessionPoolTest,IPPoolingDnsAlpn)860 TEST_F(SpdySessionPoolTest, IPPoolingDnsAlpn) {
861   // Define two hosts with identical IP address.
862   constexpr int kTestPort = 443;
863   struct TestHosts {
864     std::string name;
865     std::vector<HostResolverEndpointResult> endpoints;
866     SpdySessionKey key;
867   } test_hosts[] = {{"www.example.org"},
868                     {"mail.example.org"},
869                     {"mail.example.com"},
870                     {"example.test"}};
871 
872   const IPEndPoint kRightIP(*IPAddress::FromIPLiteral("192.168.0.1"),
873                             kTestPort);
874   const IPEndPoint kWrongIP(*IPAddress::FromIPLiteral("192.168.0.2"),
875                             kTestPort);
876   const std::string kRightALPN = "h2";
877   const std::string kWrongALPN = "h3";
878 
879   // `test_hosts[0]` and `test_hosts[1]` resolve to the same IP address, without
880   // any ALPN information.
881   test_hosts[0].endpoints.emplace_back();
882   test_hosts[0].endpoints[0].ip_endpoints = {kRightIP};
883   test_hosts[1].endpoints.emplace_back();
884   test_hosts[1].endpoints[0].ip_endpoints = {kRightIP};
885 
886   // `test_hosts[2]` resolves to the same IP address, but only via an
887   // alternative endpoint with matching ALPN.
888   test_hosts[2].endpoints.emplace_back();
889   test_hosts[2].endpoints[0].ip_endpoints = {kRightIP};
890   test_hosts[2].endpoints[0].metadata.supported_protocol_alpns = {kRightALPN};
891 
892   // `test_hosts[3]` resolves to the same IP address, but only via an
893   // alternative endpoint with a mismatching ALPN.
894   test_hosts[3].endpoints.resize(2);
895   test_hosts[3].endpoints[0].ip_endpoints = {kRightIP};
896   test_hosts[3].endpoints[0].metadata.supported_protocol_alpns = {kWrongALPN};
897   test_hosts[3].endpoints[1].ip_endpoints = {kWrongIP};
898   test_hosts[3].endpoints[1].metadata.supported_protocol_alpns = {kRightALPN};
899 
900   // Populate the HostResolver cache.
901   session_deps_.host_resolver->set_synchronous_mode(true);
902   for (auto& test_host : test_hosts) {
903     session_deps_.host_resolver->rules()->AddRule(
904         test_host.name,
905         MockHostResolverBase::RuleResolver::RuleResult(test_host.endpoints));
906 
907     test_host.key = SpdySessionKey(
908         HostPortPair(test_host.name, kTestPort), PRIVACY_MODE_DISABLED,
909         ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
910         NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
911         /*disable_cert_verification_network_fetches=*/false);
912   }
913 
914   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
915   StaticSocketDataProvider data(reads, base::span<MockWrite>());
916   MockConnect connect_data(SYNCHRONOUS, OK);
917   data.set_connect_data(connect_data);
918 
919   session_deps_.socket_factory->AddSocketDataProvider(&data);
920   AddSSLSocketData();
921 
922   CreateNetworkSession();
923 
924   // Open SpdySession to the first host.
925   base::WeakPtr<SpdySession> session0 = CreateSpdySession(
926       http_session_.get(), test_hosts[0].key, NetLogWithSource());
927 
928   // The second host should pool to the existing connection. Although the
929   // addresses are not associated with ALPNs, the default connection flow for
930   // HTTPS is compatible with HTTP/2.
931   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
932                                           test_hosts[1].endpoints));
933   base::WeakPtr<SpdySession> session1 =
934       spdy_session_pool_->FindAvailableSession(
935           test_hosts[1].key, /*enable_ip_based_pooling=*/true,
936           /*is_websocket=*/false,
937           NetLogWithSource::Make(NetLogSourceType::NONE));
938   EXPECT_EQ(session0.get(), session1.get());
939 
940   // The third host should also pool to the existing connection.
941   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[2].key,
942                                           test_hosts[2].endpoints));
943   base::WeakPtr<SpdySession> session2 =
944       spdy_session_pool_->FindAvailableSession(
945           test_hosts[2].key, /*enable_ip_based_pooling=*/true,
946           /*is_websocket=*/false,
947           NetLogWithSource::Make(NetLogSourceType::NONE));
948   EXPECT_EQ(session0.get(), session2.get());
949 
950   // The fourth host should not pool. The only matching endpoint is specific to
951   // QUIC.
952   EXPECT_FALSE(TryCreateAliasedSpdySession(
953       spdy_session_pool_, test_hosts[3].key, test_hosts[3].endpoints));
954 }
955 
TEST_F(SpdySessionPoolTest,IPPoolingDisabled)956 TEST_F(SpdySessionPoolTest, IPPoolingDisabled) {
957   // Define two hosts with identical IP address.
958   constexpr int kTestPort = 443;
959   struct TestHosts {
960     std::string name;
961     std::string iplist;
962     SpdySessionKey key;
963   } test_hosts[] = {
964       {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"},
965   };
966 
967   // Populate the HostResolver cache.
968   session_deps_.host_resolver->set_synchronous_mode(true);
969   for (auto& test_host : test_hosts) {
970     session_deps_.host_resolver->rules()->AddIPLiteralRule(
971         test_host.name, test_host.iplist, std::string());
972 
973     test_host.key = SpdySessionKey(
974         HostPortPair(test_host.name, kTestPort), PRIVACY_MODE_DISABLED,
975         ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
976         NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
977         /*disable_cert_verification_network_fetches=*/false);
978   }
979 
980   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
981   StaticSocketDataProvider data(reads, base::span<MockWrite>());
982   MockConnect connect_data(SYNCHRONOUS, OK);
983   data.set_connect_data(connect_data);
984   session_deps_.socket_factory->AddSocketDataProvider(&data);
985   AddSSLSocketData();
986 
987   MockRead reads1[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
988   StaticSocketDataProvider data1(reads1, base::span<MockWrite>());
989   MockConnect connect_data1(SYNCHRONOUS, OK);
990   data1.set_connect_data(connect_data1);
991   session_deps_.socket_factory->AddSocketDataProvider(&data1);
992   AddSSLSocketData();
993 
994   CreateNetworkSession();
995 
996   // Open SpdySession to the first host.
997   base::WeakPtr<SpdySession> session0 = CreateSpdySession(
998       http_session_.get(), test_hosts[0].key, NetLogWithSource());
999 
1000   // |test_hosts[1]| should pool to the existing connection.
1001   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
1002                                           test_hosts[1].iplist));
1003   base::WeakPtr<SpdySession> session1 =
1004       spdy_session_pool_->FindAvailableSession(
1005           test_hosts[1].key, /* enable_ip_based_pooling = */ true,
1006           /* is_websocket = */ false, NetLogWithSource());
1007   EXPECT_EQ(session0.get(), session1.get());
1008 
1009   // A request to the second host should not pool to the existing connection if
1010   // IP based pooling is disabled.
1011   session1 = spdy_session_pool_->FindAvailableSession(
1012       test_hosts[1].key, /* enable_ip_based_pooling = */ false,
1013       /* is_websocket = */ false, NetLogWithSource());
1014   EXPECT_FALSE(session1);
1015 
1016   // It should be possible to open a new SpdySession, even if a previous call to
1017   // FindAvailableSession() linked the second key to the first connection in the
1018   // IP pooled bucket of SpdySessionPool::available_session_map_.
1019   session1 = CreateSpdySessionWithIpBasedPoolingDisabled(
1020       http_session_.get(), test_hosts[1].key, NetLogWithSource());
1021   EXPECT_TRUE(session1);
1022   EXPECT_NE(session0.get(), session1.get());
1023 }
1024 
1025 // Verifies that an SSL connection with client authentication disables SPDY IP
1026 // pooling.
TEST_F(SpdySessionPoolTest,IPPoolingClientCert)1027 TEST_F(SpdySessionPoolTest, IPPoolingClientCert) {
1028   SSLSocketDataProvider ssl(ASYNC, OK);
1029   ssl.ssl_info.cert = X509Certificate::CreateFromBytes(webkit_der);
1030   ASSERT_TRUE(ssl.ssl_info.cert);
1031   ssl.ssl_info.client_cert_sent = true;
1032   ssl.next_proto = kProtoHTTP2;
1033   RunIPPoolingDisabledTest(&ssl);
1034 }
1035 
1036 namespace {
1037 enum class ChangeType {
1038   kIpAddress = 0,
1039   kSSLConfig,
1040   kCertDatabase,
1041   kCertVerifier
1042 };
1043 
1044 class SpdySessionGoAwayOnChangeTest
1045     : public SpdySessionPoolTest,
1046       public ::testing::WithParamInterface<ChangeType> {
1047  public:
SetUp()1048   void SetUp() override {
1049     SpdySessionPoolTest::SetUp();
1050 
1051     if (GetParam() == ChangeType::kIpAddress) {
1052       session_deps_.go_away_on_ip_change = true;
1053     }
1054   }
1055 
SimulateChange()1056   void SimulateChange() {
1057     switch (GetParam()) {
1058       case ChangeType::kIpAddress:
1059         spdy_session_pool_->OnIPAddressChanged();
1060         break;
1061       case ChangeType::kSSLConfig:
1062         session_deps_.ssl_config_service->NotifySSLContextConfigChange();
1063         break;
1064       case ChangeType::kCertDatabase:
1065         // TODO(mattm): For more realistic testing this should call
1066         // `CertDatabase::GetInstance()->NotifyObserversCertDBChanged()`,
1067         // however that delivers notifications asynchronously, and running
1068         // the message loop to allow the notification to be delivered allows
1069         // other parts of the tested code to advance, breaking the test
1070         // expectations.
1071         spdy_session_pool_->OnSSLConfigChanged(
1072             SSLClientContext::SSLConfigChangeType::kCertDatabaseChanged);
1073         break;
1074       case ChangeType::kCertVerifier:
1075         session_deps_.cert_verifier->SimulateOnCertVerifierChanged();
1076         break;
1077     }
1078   }
1079 
ExpectedNetError() const1080   Error ExpectedNetError() const {
1081     switch (GetParam()) {
1082       case ChangeType::kIpAddress:
1083         return ERR_NETWORK_CHANGED;
1084       case ChangeType::kSSLConfig:
1085         return ERR_NETWORK_CHANGED;
1086       case ChangeType::kCertDatabase:
1087         return ERR_CERT_DATABASE_CHANGED;
1088       case ChangeType::kCertVerifier:
1089         return ERR_CERT_VERIFIER_CHANGED;
1090     }
1091   }
1092 };
1093 }  // namespace
1094 
1095 // Construct a Pool with SpdySessions in various availability states. Simulate
1096 // an IP address change. Ensure sessions gracefully shut down. Regression test
1097 // for crbug.com/379469.
TEST_P(SpdySessionGoAwayOnChangeTest,GoAwayOnChange)1098 TEST_P(SpdySessionGoAwayOnChangeTest, GoAwayOnChange) {
1099   MockConnect connect_data(SYNCHRONOUS, OK);
1100   session_deps_.host_resolver->set_synchronous_mode(true);
1101 
1102   // This isn't testing anything having to do with SPDY frames; we
1103   // can ignore issues of how dependencies are set.  We default to
1104   // setting them (when doing the appropriate protocol) since that's
1105   // where we're eventually headed for all HTTP/2 connections.
1106   SpdyTestUtil spdy_util;
1107 
1108   MockRead reads[] = {
1109       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1110   };
1111   spdy::SpdySerializedFrame req(
1112       spdy_util.ConstructSpdyGet("http://www.example.org", 1, MEDIUM));
1113   MockWrite writes[] = {CreateMockWrite(req, 1)};
1114 
1115   StaticSocketDataProvider dataA(reads, writes);
1116   dataA.set_connect_data(connect_data);
1117   session_deps_.socket_factory->AddSocketDataProvider(&dataA);
1118 
1119   AddSSLSocketData();
1120 
1121   CreateNetworkSession();
1122 
1123   // Set up session A: Going away, but with an active stream.
1124   const std::string kTestHostA("www.example.org");
1125   HostPortPair test_host_port_pairA(kTestHostA, 80);
1126   SpdySessionKey keyA(test_host_port_pairA, PRIVACY_MODE_DISABLED,
1127                       ProxyChain::Direct(), SessionUsage::kDestination,
1128                       SocketTag(), NetworkAnonymizationKey(),
1129                       SecureDnsPolicy::kAllow,
1130                       /*disable_cert_verification_network_fetches=*/false);
1131   base::WeakPtr<SpdySession> sessionA =
1132       CreateSpdySession(http_session_.get(), keyA, NetLogWithSource());
1133 
1134   GURL urlA("http://www.example.org");
1135   base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
1136       SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, NetLogWithSource());
1137   test::StreamDelegateDoNothing delegateA(spdy_streamA);
1138   spdy_streamA->SetDelegate(&delegateA);
1139 
1140   spdy::Http2HeaderBlock headers(
1141       spdy_util.ConstructGetHeaderBlock(urlA.spec()));
1142   spdy_streamA->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1143 
1144   base::RunLoop().RunUntilIdle();  // Allow headers to write.
1145   EXPECT_TRUE(delegateA.send_headers_completed());
1146 
1147   sessionA->MakeUnavailable();
1148   EXPECT_TRUE(sessionA->IsGoingAway());
1149   EXPECT_FALSE(delegateA.StreamIsClosed());
1150 
1151   // Set up session B: Available, with a created stream.
1152   StaticSocketDataProvider dataB(reads, writes);
1153   dataB.set_connect_data(connect_data);
1154   session_deps_.socket_factory->AddSocketDataProvider(&dataB);
1155 
1156   AddSSLSocketData();
1157 
1158   const std::string kTestHostB("mail.example.org");
1159   HostPortPair test_host_port_pairB(kTestHostB, 80);
1160   SpdySessionKey keyB(test_host_port_pairB, PRIVACY_MODE_DISABLED,
1161                       ProxyChain::Direct(), SessionUsage::kDestination,
1162                       SocketTag(), NetworkAnonymizationKey(),
1163                       SecureDnsPolicy::kAllow,
1164                       /*disable_cert_verification_network_fetches=*/false);
1165   base::WeakPtr<SpdySession> sessionB =
1166       CreateSpdySession(http_session_.get(), keyB, NetLogWithSource());
1167   EXPECT_TRUE(sessionB->IsAvailable());
1168 
1169   GURL urlB("http://mail.example.org");
1170   base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
1171       SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, NetLogWithSource());
1172   test::StreamDelegateDoNothing delegateB(spdy_streamB);
1173   spdy_streamB->SetDelegate(&delegateB);
1174 
1175   // Set up session C: Draining.
1176   StaticSocketDataProvider dataC(reads, writes);
1177   dataC.set_connect_data(connect_data);
1178   session_deps_.socket_factory->AddSocketDataProvider(&dataC);
1179 
1180   AddSSLSocketData();
1181 
1182   const std::string kTestHostC("mail.example.com");
1183   HostPortPair test_host_port_pairC(kTestHostC, 80);
1184   SpdySessionKey keyC(test_host_port_pairC, PRIVACY_MODE_DISABLED,
1185                       ProxyChain::Direct(), SessionUsage::kDestination,
1186                       SocketTag(), NetworkAnonymizationKey(),
1187                       SecureDnsPolicy::kAllow,
1188                       /*disable_cert_verification_network_fetches=*/false);
1189   base::WeakPtr<SpdySession> sessionC =
1190       CreateSpdySession(http_session_.get(), keyC, NetLogWithSource());
1191 
1192   sessionC->CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, "Error!");
1193   EXPECT_TRUE(sessionC->IsDraining());
1194 
1195   SimulateChange();
1196 
1197   EXPECT_TRUE(sessionA->IsGoingAway());
1198   EXPECT_TRUE(sessionB->IsDraining());
1199   EXPECT_TRUE(sessionC->IsDraining());
1200 
1201   EXPECT_EQ(1u,
1202             num_active_streams(sessionA));  // Active stream is still active.
1203   EXPECT_FALSE(delegateA.StreamIsClosed());
1204 
1205   EXPECT_TRUE(delegateB.StreamIsClosed());  // Created stream was closed.
1206   EXPECT_THAT(delegateB.WaitForClose(), IsError(ExpectedNetError()));
1207 
1208   sessionA->CloseSessionOnError(ERR_ABORTED, "Closing");
1209   sessionB->CloseSessionOnError(ERR_ABORTED, "Closing");
1210 
1211   EXPECT_TRUE(delegateA.StreamIsClosed());
1212   EXPECT_THAT(delegateA.WaitForClose(), IsError(ERR_ABORTED));
1213 }
1214 
1215 INSTANTIATE_TEST_SUITE_P(All,
1216                          SpdySessionGoAwayOnChangeTest,
1217                          testing::Values(ChangeType::kIpAddress,
1218                                          ChangeType::kSSLConfig,
1219                                          ChangeType::kCertDatabase,
1220                                          ChangeType::kCertVerifier));
1221 
1222 // Construct a Pool with SpdySessions in various availability states. Simulate
1223 // an IP address change. Ensure sessions gracefully shut down. Regression test
1224 // for crbug.com/379469.
TEST_F(SpdySessionPoolTest,CloseOnIPAddressChanged)1225 TEST_F(SpdySessionPoolTest, CloseOnIPAddressChanged) {
1226   MockConnect connect_data(SYNCHRONOUS, OK);
1227   session_deps_.host_resolver->set_synchronous_mode(true);
1228 
1229   // This isn't testing anything having to do with SPDY frames; we
1230   // can ignore issues of how dependencies are set.  We default to
1231   // setting them (when doing the appropriate protocol) since that's
1232   // where we're eventually headed for all HTTP/2 connections.
1233   SpdyTestUtil spdy_util;
1234 
1235   MockRead reads[] = {
1236       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1237   };
1238   spdy::SpdySerializedFrame req(
1239       spdy_util.ConstructSpdyGet("http://www.example.org", 1, MEDIUM));
1240   MockWrite writes[] = {CreateMockWrite(req, 1)};
1241 
1242   StaticSocketDataProvider dataA(reads, writes);
1243   dataA.set_connect_data(connect_data);
1244   session_deps_.socket_factory->AddSocketDataProvider(&dataA);
1245 
1246   AddSSLSocketData();
1247 
1248   session_deps_.go_away_on_ip_change = false;
1249   CreateNetworkSession();
1250 
1251   // Set up session A: Going away, but with an active stream.
1252   const std::string kTestHostA("www.example.org");
1253   HostPortPair test_host_port_pairA(kTestHostA, 80);
1254   SpdySessionKey keyA(test_host_port_pairA, PRIVACY_MODE_DISABLED,
1255                       ProxyChain::Direct(), SessionUsage::kDestination,
1256                       SocketTag(), NetworkAnonymizationKey(),
1257                       SecureDnsPolicy::kAllow,
1258                       /*disable_cert_verification_network_fetches=*/false);
1259   base::WeakPtr<SpdySession> sessionA =
1260       CreateSpdySession(http_session_.get(), keyA, NetLogWithSource());
1261 
1262   GURL urlA("http://www.example.org");
1263   base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
1264       SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, NetLogWithSource());
1265   test::StreamDelegateDoNothing delegateA(spdy_streamA);
1266   spdy_streamA->SetDelegate(&delegateA);
1267 
1268   spdy::Http2HeaderBlock headers(
1269       spdy_util.ConstructGetHeaderBlock(urlA.spec()));
1270   spdy_streamA->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1271 
1272   base::RunLoop().RunUntilIdle();  // Allow headers to write.
1273   EXPECT_TRUE(delegateA.send_headers_completed());
1274 
1275   sessionA->MakeUnavailable();
1276   EXPECT_TRUE(sessionA->IsGoingAway());
1277   EXPECT_FALSE(delegateA.StreamIsClosed());
1278 
1279   // Set up session B: Available, with a created stream.
1280   StaticSocketDataProvider dataB(reads, writes);
1281   dataB.set_connect_data(connect_data);
1282   session_deps_.socket_factory->AddSocketDataProvider(&dataB);
1283 
1284   AddSSLSocketData();
1285 
1286   const std::string kTestHostB("mail.example.org");
1287   HostPortPair test_host_port_pairB(kTestHostB, 80);
1288   SpdySessionKey keyB(test_host_port_pairB, PRIVACY_MODE_DISABLED,
1289                       ProxyChain::Direct(), SessionUsage::kDestination,
1290                       SocketTag(), NetworkAnonymizationKey(),
1291                       SecureDnsPolicy::kAllow,
1292                       /*disable_cert_verification_network_fetches=*/false);
1293   base::WeakPtr<SpdySession> sessionB =
1294       CreateSpdySession(http_session_.get(), keyB, NetLogWithSource());
1295   EXPECT_TRUE(sessionB->IsAvailable());
1296 
1297   GURL urlB("http://mail.example.org");
1298   base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
1299       SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, NetLogWithSource());
1300   test::StreamDelegateDoNothing delegateB(spdy_streamB);
1301   spdy_streamB->SetDelegate(&delegateB);
1302 
1303   // Set up session C: Draining.
1304   StaticSocketDataProvider dataC(reads, writes);
1305   dataC.set_connect_data(connect_data);
1306   session_deps_.socket_factory->AddSocketDataProvider(&dataC);
1307 
1308   AddSSLSocketData();
1309 
1310   const std::string kTestHostC("mail.example.com");
1311   HostPortPair test_host_port_pairC(kTestHostC, 80);
1312   SpdySessionKey keyC(test_host_port_pairC, PRIVACY_MODE_DISABLED,
1313                       ProxyChain::Direct(), SessionUsage::kDestination,
1314                       SocketTag(), NetworkAnonymizationKey(),
1315                       SecureDnsPolicy::kAllow,
1316                       /*disable_cert_verification_network_fetches=*/false);
1317   base::WeakPtr<SpdySession> sessionC =
1318       CreateSpdySession(http_session_.get(), keyC, NetLogWithSource());
1319 
1320   sessionC->CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, "Error!");
1321   EXPECT_TRUE(sessionC->IsDraining());
1322 
1323   spdy_session_pool_->OnIPAddressChanged();
1324 
1325   EXPECT_TRUE(sessionA->IsDraining());
1326   EXPECT_TRUE(sessionB->IsDraining());
1327   EXPECT_TRUE(sessionC->IsDraining());
1328 
1329   // Both streams were closed with an error.
1330   EXPECT_TRUE(delegateA.StreamIsClosed());
1331   EXPECT_THAT(delegateA.WaitForClose(), IsError(ERR_NETWORK_CHANGED));
1332   EXPECT_TRUE(delegateB.StreamIsClosed());
1333   EXPECT_THAT(delegateB.WaitForClose(), IsError(ERR_NETWORK_CHANGED));
1334 }
1335 
1336 // Regression test for https://crbug.com/789791.
TEST_F(SpdySessionPoolTest,HandleIPAddressChangeThenShutdown)1337 TEST_F(SpdySessionPoolTest, HandleIPAddressChangeThenShutdown) {
1338   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
1339   SpdyTestUtil spdy_util;
1340   spdy::SpdySerializedFrame req(
1341       spdy_util.ConstructSpdyGet(kDefaultUrl, 1, MEDIUM));
1342   MockWrite writes[] = {CreateMockWrite(req, 1)};
1343   StaticSocketDataProvider data(reads, writes);
1344 
1345   MockConnect connect_data(SYNCHRONOUS, OK);
1346   data.set_connect_data(connect_data);
1347 
1348   session_deps_.socket_factory->AddSocketDataProvider(&data);
1349   AddSSLSocketData();
1350 
1351   CreateNetworkSession();
1352 
1353   const GURL url(kDefaultUrl);
1354   SpdySessionKey key(HostPortPair::FromURL(url), PRIVACY_MODE_DISABLED,
1355                      ProxyChain::Direct(), SessionUsage::kDestination,
1356                      SocketTag(), NetworkAnonymizationKey(),
1357                      SecureDnsPolicy::kAllow,
1358                      /*disable_cert_verification_network_fetches=*/false);
1359   base::WeakPtr<SpdySession> session =
1360       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1361 
1362   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1363       SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, NetLogWithSource());
1364   test::StreamDelegateDoNothing delegate(spdy_stream);
1365   spdy_stream->SetDelegate(&delegate);
1366 
1367   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1368   spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1369 
1370   base::RunLoop().RunUntilIdle();
1371   EXPECT_TRUE(delegate.send_headers_completed());
1372 
1373   spdy_session_pool_->OnIPAddressChanged();
1374 
1375 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
1376   EXPECT_EQ(1u, num_active_streams(session));
1377   EXPECT_TRUE(session->IsGoingAway());
1378   EXPECT_FALSE(session->IsDraining());
1379 #else
1380   EXPECT_EQ(0u, num_active_streams(session));
1381   EXPECT_FALSE(session->IsGoingAway());
1382   EXPECT_TRUE(session->IsDraining());
1383 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
1384 
1385   http_session_.reset();
1386 
1387   data.AllReadDataConsumed();
1388   data.AllWriteDataConsumed();
1389 }
1390 
1391 // Regression test for https://crbug.com/789791.
TEST_F(SpdySessionPoolTest,HandleGracefulGoawayThenShutdown)1392 TEST_F(SpdySessionPoolTest, HandleGracefulGoawayThenShutdown) {
1393   SpdyTestUtil spdy_util;
1394   spdy::SpdySerializedFrame goaway(spdy_util.ConstructSpdyGoAway(
1395       0x7fffffff, spdy::ERROR_CODE_NO_ERROR, "Graceful shutdown."));
1396   MockRead reads[] = {
1397       MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(goaway, 2),
1398       MockRead(ASYNC, ERR_IO_PENDING, 3), MockRead(ASYNC, OK, 4)};
1399   spdy::SpdySerializedFrame req(
1400       spdy_util.ConstructSpdyGet(kDefaultUrl, 1, MEDIUM));
1401   MockWrite writes[] = {CreateMockWrite(req, 0)};
1402   SequencedSocketData data(reads, writes);
1403 
1404   MockConnect connect_data(SYNCHRONOUS, OK);
1405   data.set_connect_data(connect_data);
1406 
1407   session_deps_.socket_factory->AddSocketDataProvider(&data);
1408   AddSSLSocketData();
1409 
1410   CreateNetworkSession();
1411 
1412   const GURL url(kDefaultUrl);
1413   SpdySessionKey key(HostPortPair::FromURL(url), PRIVACY_MODE_DISABLED,
1414                      ProxyChain::Direct(), SessionUsage::kDestination,
1415                      SocketTag(), NetworkAnonymizationKey(),
1416                      SecureDnsPolicy::kAllow,
1417                      /*disable_cert_verification_network_fetches=*/false);
1418   base::WeakPtr<SpdySession> session =
1419       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1420 
1421   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1422       SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, NetLogWithSource());
1423   test::StreamDelegateDoNothing delegate(spdy_stream);
1424   spdy_stream->SetDelegate(&delegate);
1425 
1426   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1427   spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1428 
1429   // Send headers.
1430   base::RunLoop().RunUntilIdle();
1431   EXPECT_TRUE(delegate.send_headers_completed());
1432 
1433   EXPECT_EQ(1u, num_active_streams(session));
1434   EXPECT_FALSE(session->IsGoingAway());
1435   EXPECT_FALSE(session->IsDraining());
1436 
1437   // Read GOAWAY.
1438   data.Resume();
1439   base::RunLoop().RunUntilIdle();
1440 
1441   EXPECT_EQ(1u, num_active_streams(session));
1442   EXPECT_TRUE(session->IsGoingAway());
1443   EXPECT_FALSE(session->IsDraining());
1444 
1445   http_session_.reset();
1446 
1447   data.AllReadDataConsumed();
1448   data.AllWriteDataConsumed();
1449 }
1450 
TEST_F(SpdySessionPoolTest,IPConnectionPoolingWithWebSockets)1451 TEST_F(SpdySessionPoolTest, IPConnectionPoolingWithWebSockets) {
1452   // Define two hosts with identical IP address.
1453   const int kTestPort = 443;
1454   struct TestHosts {
1455     std::string name;
1456     std::string iplist;
1457     SpdySessionKey key;
1458   } test_hosts[] = {
1459       {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"},
1460   };
1461 
1462   // Populate the HostResolver cache.
1463   session_deps_.host_resolver->set_synchronous_mode(true);
1464   for (auto& test_host : test_hosts) {
1465     session_deps_.host_resolver->rules()->AddIPLiteralRule(
1466         test_host.name, test_host.iplist, std::string());
1467 
1468     test_host.key = SpdySessionKey(
1469         HostPortPair(test_host.name, kTestPort), PRIVACY_MODE_DISABLED,
1470         ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
1471         NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
1472         /*disable_cert_verification_network_fetches=*/false);
1473   }
1474 
1475   SpdyTestUtil spdy_util;
1476 
1477   spdy::SpdySerializedFrame req(
1478       spdy_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1479   spdy::SpdySerializedFrame settings_ack(spdy_util.ConstructSpdySettingsAck());
1480   MockWrite writes[] = {CreateMockWrite(req, 0),
1481                         CreateMockWrite(settings_ack, 2)};
1482 
1483   spdy::SettingsMap settings;
1484   settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
1485   spdy::SpdySerializedFrame settings_frame(
1486       spdy_util.ConstructSpdySettings(settings));
1487   spdy::SpdySerializedFrame resp(
1488       spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
1489   spdy::SpdySerializedFrame body(spdy_util.ConstructSpdyDataFrame(1, true));
1490   MockRead reads[] = {CreateMockRead(settings_frame, 1),
1491                       CreateMockRead(resp, 3), CreateMockRead(body, 4),
1492                       MockRead(ASYNC, ERR_IO_PENDING, 5),
1493                       MockRead(ASYNC, 0, 6)};
1494 
1495   SequencedSocketData data(reads, writes);
1496   session_deps_.socket_factory->AddSocketDataProvider(&data);
1497   AddSSLSocketData();
1498   CreateNetworkSession();
1499 
1500   // Create a connection to the first host.
1501   base::WeakPtr<SpdySession> session = CreateSpdySession(
1502       http_session_.get(), test_hosts[0].key, NetLogWithSource());
1503 
1504   // SpdySession does not support Websocket before SETTINGS frame is read.
1505   EXPECT_FALSE(session->support_websocket());
1506   NetLogWithSource net_log_with_source{
1507       NetLogWithSource::Make(NetLogSourceType::NONE)};
1508   // TryCreateAliasedSpdySession should not find |session| for either
1509   // SpdySessionKeys if |is_websocket| argument is set.
1510   EXPECT_FALSE(TryCreateAliasedSpdySession(
1511       spdy_session_pool_, test_hosts[0].key, test_hosts[0].iplist,
1512       /* enable_ip_based_pooling = */ true,
1513       /* is_websocket = */ true));
1514   EXPECT_FALSE(TryCreateAliasedSpdySession(
1515       spdy_session_pool_, test_hosts[1].key, test_hosts[1].iplist,
1516       /* enable_ip_based_pooling = */ true,
1517       /* is_websocket = */ true));
1518 
1519   // Start request that triggers reading the SETTINGS frame.
1520   const GURL url(kDefaultUrl);
1521   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1522       SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, NetLogWithSource());
1523   test::StreamDelegateDoNothing delegate(spdy_stream);
1524   spdy_stream->SetDelegate(&delegate);
1525 
1526   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1527   spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1528 
1529   base::RunLoop().RunUntilIdle();
1530 
1531   // Now SpdySession has read the SETTINGS frame and thus supports Websocket.
1532   EXPECT_TRUE(session->support_websocket());
1533 
1534   // FindAvailableSession() on the first host should now find the existing
1535   // session with websockets enabled, and TryCreateAliasedSpdySession() should
1536   // now set up aliases for |session| for the second one.
1537   base::WeakPtr<SpdySession> result = spdy_session_pool_->FindAvailableSession(
1538       test_hosts[0].key, /* enable_ip_based_pooling = */ true,
1539       /* is_websocket = */ true, net_log_with_source);
1540   EXPECT_EQ(session.get(), result.get());
1541   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
1542                                           test_hosts[1].iplist,
1543                                           /* enable_ip_based_pooling = */ true,
1544                                           /* is_websocket = */ true));
1545 
1546   // FindAvailableSession() should return |session| for either SpdySessionKeys
1547   // when IP based pooling is enabled.
1548   result = spdy_session_pool_->FindAvailableSession(
1549       test_hosts[0].key, /* enable_ip_based_pooling = */ true,
1550       /* is_websocket = */ true, net_log_with_source);
1551   EXPECT_EQ(session.get(), result.get());
1552   result = spdy_session_pool_->FindAvailableSession(
1553       test_hosts[1].key, /* enable_ip_based_pooling = */ true,
1554       /* is_websocket = */ true, net_log_with_source);
1555   EXPECT_EQ(session.get(), result.get());
1556 
1557   // FindAvailableSession() should only return |session| for the first
1558   // SpdySessionKey when IP based pooling is disabled.
1559   result = spdy_session_pool_->FindAvailableSession(
1560       test_hosts[0].key, /* enable_ip_based_pooling = */ false,
1561       /* is_websocket = */ true, net_log_with_source);
1562   EXPECT_EQ(session.get(), result.get());
1563   result = spdy_session_pool_->FindAvailableSession(
1564       test_hosts[1].key, /* enable_ip_based_pooling = */ false,
1565       /* is_websocket = */ true, net_log_with_source);
1566   EXPECT_FALSE(result);
1567 
1568   // Read EOF.
1569   data.Resume();
1570   base::RunLoop().RunUntilIdle();
1571 
1572   EXPECT_TRUE(data.AllReadDataConsumed());
1573   EXPECT_TRUE(data.AllWriteDataConsumed());
1574 }
1575 
1576 class TestOnRequestDeletedCallback {
1577  public:
1578   TestOnRequestDeletedCallback() = default;
1579 
1580   TestOnRequestDeletedCallback(const TestOnRequestDeletedCallback&) = delete;
1581   TestOnRequestDeletedCallback& operator=(const TestOnRequestDeletedCallback&) =
1582       delete;
1583 
1584   ~TestOnRequestDeletedCallback() = default;
1585 
Callback()1586   base::RepeatingClosure Callback() {
1587     return base::BindRepeating(&TestOnRequestDeletedCallback::OnRequestDeleted,
1588                                base::Unretained(this));
1589   }
1590 
invoked() const1591   bool invoked() const { return invoked_; }
1592 
WaitUntilInvoked()1593   void WaitUntilInvoked() { run_loop_.Run(); }
1594 
SetRequestDeletedCallback(base::OnceClosure request_deleted_callback)1595   void SetRequestDeletedCallback(base::OnceClosure request_deleted_callback) {
1596     DCHECK(!request_deleted_callback_);
1597     request_deleted_callback_ = std::move(request_deleted_callback);
1598   }
1599 
1600  private:
OnRequestDeleted()1601   void OnRequestDeleted() {
1602     EXPECT_FALSE(invoked_);
1603     invoked_ = true;
1604     if (request_deleted_callback_)
1605       std::move(request_deleted_callback_).Run();
1606     run_loop_.Quit();
1607   }
1608 
1609   bool invoked_ = false;
1610   base::RunLoop run_loop_;
1611 
1612   base::OnceClosure request_deleted_callback_;
1613 };
1614 
1615 class TestRequestDelegate
1616     : public SpdySessionPool::SpdySessionRequest::Delegate {
1617  public:
1618   TestRequestDelegate() = default;
1619 
1620   TestRequestDelegate(const TestRequestDelegate&) = delete;
1621   TestRequestDelegate& operator=(const TestRequestDelegate&) = delete;
1622 
1623   ~TestRequestDelegate() override = default;
1624 
1625   // SpdySessionPool::SpdySessionRequest::Delegate implementation:
OnSpdySessionAvailable(base::WeakPtr<SpdySession> spdy_session)1626   void OnSpdySessionAvailable(
1627       base::WeakPtr<SpdySession> spdy_session) override {}
1628 };
1629 
TEST_F(SpdySessionPoolTest,RequestSessionWithNoSessions)1630 TEST_F(SpdySessionPoolTest, RequestSessionWithNoSessions) {
1631   const SpdySessionKey kSessionKey(
1632       HostPortPair("foo.test", 443), PRIVACY_MODE_DISABLED,
1633       ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
1634       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
1635       /*disable_cert_verification_network_fetches=*/false);
1636 
1637   CreateNetworkSession();
1638 
1639   // First request. Its request deleted callback should never be invoked.
1640   TestOnRequestDeletedCallback request_deleted_callback1;
1641   TestRequestDelegate request_delegate1;
1642   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request1;
1643   bool is_first_request_for_session;
1644   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1645       kSessionKey, /* enable_ip_based_pooling = */ false,
1646       /* is_websocket = */ false, NetLogWithSource(),
1647       request_deleted_callback1.Callback(), &request_delegate1,
1648       &spdy_session_request1, &is_first_request_for_session));
1649   EXPECT_TRUE(is_first_request_for_session);
1650 
1651   // Second request.
1652   TestOnRequestDeletedCallback request_deleted_callback2;
1653   TestRequestDelegate request_delegate2;
1654   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request2;
1655   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1656       kSessionKey, /* enable_ip_based_pooling = */ false,
1657       /* is_websocket = */ false, NetLogWithSource(),
1658       request_deleted_callback2.Callback(), &request_delegate2,
1659       &spdy_session_request2, &is_first_request_for_session));
1660   EXPECT_FALSE(is_first_request_for_session);
1661 
1662   // Third request.
1663   TestOnRequestDeletedCallback request_deleted_callback3;
1664   TestRequestDelegate request_delegate3;
1665   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request3;
1666   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1667       kSessionKey, /* enable_ip_based_pooling = */ false,
1668       /* is_websocket = */ false, NetLogWithSource(),
1669       request_deleted_callback3.Callback(), &request_delegate3,
1670       &spdy_session_request3, &is_first_request_for_session));
1671   EXPECT_FALSE(is_first_request_for_session);
1672 
1673   // Destroying the second request shouldn't cause anything to happen.
1674   spdy_session_request2.reset();
1675   base::RunLoop().RunUntilIdle();
1676   EXPECT_FALSE(request_deleted_callback1.invoked());
1677   EXPECT_FALSE(request_deleted_callback2.invoked());
1678   EXPECT_FALSE(request_deleted_callback3.invoked());
1679 
1680   // But destroying the first request should cause the second and third
1681   // callbacks to be invoked.
1682   spdy_session_request1.reset();
1683   request_deleted_callback2.WaitUntilInvoked();
1684   request_deleted_callback3.WaitUntilInvoked();
1685   EXPECT_FALSE(request_deleted_callback1.invoked());
1686 
1687   // Nothing should happen when the third request is destroyed.
1688   spdy_session_request3.reset();
1689   base::RunLoop().RunUntilIdle();
1690   EXPECT_FALSE(request_deleted_callback1.invoked());
1691 }
1692 
TEST_F(SpdySessionPoolTest,RequestSessionDuringNotification)1693 TEST_F(SpdySessionPoolTest, RequestSessionDuringNotification) {
1694   const SpdySessionKey kSessionKey(
1695       HostPortPair("foo.test", 443), PRIVACY_MODE_DISABLED,
1696       ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
1697       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
1698       /*disable_cert_verification_network_fetches=*/false);
1699 
1700   CreateNetworkSession();
1701 
1702   // First request. Its request deleted callback should never be invoked.
1703   TestOnRequestDeletedCallback request_deleted_callback1;
1704   TestRequestDelegate request_delegate1;
1705   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request1;
1706   bool is_first_request_for_session;
1707   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1708       kSessionKey, /* enable_ip_based_pooling = */ false,
1709       /* is_websocket = */ false, NetLogWithSource(),
1710       request_deleted_callback1.Callback(), &request_delegate1,
1711       &spdy_session_request1, &is_first_request_for_session));
1712   EXPECT_TRUE(is_first_request_for_session);
1713 
1714   // Second request.
1715   TestOnRequestDeletedCallback request_deleted_callback2;
1716   TestRequestDelegate request_delegate2;
1717   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request2;
1718   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1719       kSessionKey, /* enable_ip_based_pooling = */ false,
1720       /* is_websocket = */ false, NetLogWithSource(),
1721       request_deleted_callback2.Callback(), &request_delegate2,
1722       &spdy_session_request2, &is_first_request_for_session));
1723   EXPECT_FALSE(is_first_request_for_session);
1724 
1725   TestOnRequestDeletedCallback request_deleted_callback3;
1726   TestRequestDelegate request_delegate3;
1727   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request3;
1728   TestOnRequestDeletedCallback request_deleted_callback4;
1729   TestRequestDelegate request_delegate4;
1730   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request4;
1731   request_deleted_callback2.SetRequestDeletedCallback(
1732       base::BindLambdaForTesting([&]() {
1733         // Third request. It should again be marked as the first request for the
1734         // session, since it's only created after the original two have been
1735         // removed.
1736         bool is_first_request_for_session;
1737         EXPECT_FALSE(spdy_session_pool_->RequestSession(
1738             kSessionKey, /* enable_ip_based_pooling = */ false,
1739             /* is_websocket = */ false, NetLogWithSource(),
1740             request_deleted_callback3.Callback(), &request_delegate3,
1741             &spdy_session_request3, &is_first_request_for_session));
1742         EXPECT_TRUE(is_first_request_for_session);
1743 
1744         // Fourth request.
1745         EXPECT_FALSE(spdy_session_pool_->RequestSession(
1746             kSessionKey, /* enable_ip_based_pooling = */ false,
1747             /* is_websocket = */ false, NetLogWithSource(),
1748             request_deleted_callback4.Callback(), &request_delegate4,
1749             &spdy_session_request4, &is_first_request_for_session));
1750         EXPECT_FALSE(is_first_request_for_session);
1751       }));
1752 
1753   // Destroying the first request should cause the second callback to be
1754   // invoked, and the third and fourth request to be made.
1755   spdy_session_request1.reset();
1756   request_deleted_callback2.WaitUntilInvoked();
1757   base::RunLoop().RunUntilIdle();
1758   EXPECT_FALSE(request_deleted_callback1.invoked());
1759   EXPECT_FALSE(request_deleted_callback3.invoked());
1760   EXPECT_FALSE(request_deleted_callback4.invoked());
1761   EXPECT_TRUE(spdy_session_request3);
1762   EXPECT_TRUE(spdy_session_request4);
1763 
1764   // Destroying the third request should cause the fourth callback to be
1765   // invoked.
1766   spdy_session_request3.reset();
1767   request_deleted_callback4.WaitUntilInvoked();
1768   EXPECT_FALSE(request_deleted_callback1.invoked());
1769   EXPECT_FALSE(request_deleted_callback3.invoked());
1770 }
1771 
1772 static const char kSSLServerTestHost[] = "config-changed.test";
1773 
1774 static const struct {
1775   const char* url;
1776   const char* proxy_pac_string;
1777   bool expect_invalidated;
1778 } kSSLServerTests[] = {
1779     // If the host and port match, the session should be invalidated.
1780     {"https://config-changed.test", "DIRECT", true},
1781     // If host and port do not match, the session should not be invalidated.
1782     {"https://mail.config-changed.test", "DIRECT", false},
1783     {"https://config-changed.test:444", "DIRECT", false},
1784     // If the proxy matches, the session should be invalidated independent of
1785     // the host.
1786     {"https://config-changed.test", "HTTPS config-changed.test:443", true},
1787     {"https://mail.config-changed.test", "HTTPS config-changed.test:443", true},
1788     // HTTP and SOCKS proxies do not have client certificates.
1789     {"https://mail.config-changed.test", "PROXY config-changed.test:443",
1790      false},
1791     {"https://mail.config-changed.test", "SOCKS5 config-changed.test:443",
1792      false},
1793     // The proxy host and port must match.
1794     {"https://mail.config-changed.test", "HTTPS mail.config-changed.test:443",
1795      false},
1796     {"https://mail.config-changed.test", "HTTPS config-changed.test:444",
1797      false},
1798 };
1799 
1800 // Tests the OnSSLConfigForServersChanged() method matches SpdySessions as
1801 // expected.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChanged)1802 TEST_F(SpdySessionPoolTest, SSLConfigForServerChanged) {
1803   const MockConnect connect_data(SYNCHRONOUS, OK);
1804   const MockRead reads[] = {
1805       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1806   };
1807 
1808   std::vector<std::unique_ptr<StaticSocketDataProvider>> socket_data;
1809   size_t num_tests = std::size(kSSLServerTests);
1810   for (size_t i = 0; i < num_tests; i++) {
1811     socket_data.push_back(std::make_unique<StaticSocketDataProvider>(
1812         reads, base::span<MockWrite>()));
1813     socket_data.back()->set_connect_data(connect_data);
1814     session_deps_.socket_factory->AddSocketDataProvider(
1815         socket_data.back().get());
1816     AddSSLSocketData();
1817   }
1818 
1819   CreateNetworkSession();
1820 
1821   std::vector<base::WeakPtr<SpdySession>> sessions;
1822   for (size_t i = 0; i < num_tests; i++) {
1823     SpdySessionKey key(
1824         HostPortPair::FromURL(GURL(kSSLServerTests[i].url)),
1825         PRIVACY_MODE_DISABLED,
1826         PacResultElementToProxyChain(kSSLServerTests[i].proxy_pac_string),
1827         SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
1828         SecureDnsPolicy::kAllow,
1829         /*disable_cert_verification_network_fetches=*/false);
1830     sessions.push_back(
1831         CreateSpdySession(http_session_.get(), key, NetLogWithSource()));
1832   }
1833 
1834   // All sessions are available.
1835   for (size_t i = 0; i < num_tests; i++) {
1836     SCOPED_TRACE(i);
1837     EXPECT_TRUE(sessions[i]->IsAvailable());
1838   }
1839 
1840   spdy_session_pool_->OnSSLConfigForServersChanged(
1841       {HostPortPair(kSSLServerTestHost, 443)});
1842   base::RunLoop().RunUntilIdle();
1843 
1844   // Sessions were inactive, so the unavailable sessions are closed.
1845   for (size_t i = 0; i < num_tests; i++) {
1846     SCOPED_TRACE(i);
1847     if (kSSLServerTests[i].expect_invalidated) {
1848       EXPECT_FALSE(sessions[i]);
1849     } else {
1850       ASSERT_TRUE(sessions[i]);
1851       EXPECT_TRUE(sessions[i]->IsAvailable());
1852     }
1853   }
1854 }
1855 
1856 // Tests the OnSSLConfigForServersChanged() method matches SpdySessions
1857 // containing proxy chains.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChangedWithProxyChain)1858 TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithProxyChain) {
1859   const MockConnect connect_data(SYNCHRONOUS, OK);
1860   const MockRead reads[] = {
1861       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1862   };
1863 
1864   ProxyChain proxy_chain({
1865       ProxyServer::FromSchemeHostAndPort(ProxyServer::Scheme::SCHEME_HTTPS,
1866                                          "proxya", 443),
1867       ProxyServer::FromSchemeHostAndPort(ProxyServer::Scheme::SCHEME_HTTPS,
1868                                          "proxyb", 443),
1869       ProxyServer::FromSchemeHostAndPort(ProxyServer::Scheme::SCHEME_HTTPS,
1870                                          "proxyc", 443),
1871   });
1872 
1873   std::vector<std::unique_ptr<StaticSocketDataProvider>> socket_data;
1874   socket_data.push_back(std::make_unique<StaticSocketDataProvider>(
1875       reads, base::span<MockWrite>()));
1876   socket_data.back()->set_connect_data(connect_data);
1877   session_deps_.socket_factory->AddSocketDataProvider(socket_data.back().get());
1878   AddSSLSocketData();
1879 
1880   CreateNetworkSession();
1881 
1882   SpdySessionKey key(HostPortPair::FromURL(GURL("https://example.com")),
1883                      PRIVACY_MODE_DISABLED, proxy_chain,
1884                      SessionUsage::kDestination, SocketTag(),
1885                      NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
1886                      /*disable_cert_verification_network_fetches=*/false);
1887   base::WeakPtr<SpdySession> session =
1888       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1889 
1890   EXPECT_TRUE(session->IsAvailable());
1891 
1892   spdy_session_pool_->OnSSLConfigForServersChanged(
1893       {HostPortPair("proxyb", 443)});
1894   base::RunLoop().RunUntilIdle();
1895 
1896   // The unavailable session is closed.
1897   EXPECT_FALSE(session);
1898 }
1899 
1900 // Tests the OnSSLConfigForServersChanged() method when there are streams open.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChangedWithStreams)1901 TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithStreams) {
1902   // Set up a SpdySession with an active, created, and pending stream.
1903   SpdyTestUtil spdy_util;
1904   spdy::SettingsMap settings;
1905   settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 2;
1906   spdy::SpdySerializedFrame settings_frame =
1907       spdy_util.ConstructSpdySettings(settings);
1908   spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck();
1909   spdy::SpdySerializedFrame req(
1910       spdy_util.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
1911 
1912   const MockConnect connect_data(SYNCHRONOUS, OK);
1913   const MockRead reads[] = {
1914       CreateMockRead(settings_frame),
1915       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1916   };
1917   const MockWrite writes[] = {
1918       CreateMockWrite(settings_ack),
1919       CreateMockWrite(req),
1920   };
1921 
1922   StaticSocketDataProvider socket_data(reads, writes);
1923   socket_data.set_connect_data(connect_data);
1924   session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
1925   AddSSLSocketData();
1926 
1927   CreateNetworkSession();
1928 
1929   const GURL url(kDefaultUrl);
1930   SpdySessionKey key(HostPortPair::FromURL(url), PRIVACY_MODE_DISABLED,
1931                      ProxyChain::Direct(), SessionUsage::kDestination,
1932                      SocketTag(), NetworkAnonymizationKey(),
1933                      SecureDnsPolicy::kAllow,
1934                      /*disable_cert_verification_network_fetches=*/false);
1935   base::WeakPtr<SpdySession> session =
1936       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1937 
1938   // Pick up the SETTINGS frame to update SETTINGS_MAX_CONCURRENT_STREAMS.
1939   base::RunLoop().RunUntilIdle();
1940   EXPECT_EQ(2u, max_concurrent_streams(session));
1941 
1942   // The first two stream requests should succeed.
1943   base::WeakPtr<SpdyStream> active_stream = CreateStreamSynchronously(
1944       SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, NetLogWithSource());
1945   test::StreamDelegateDoNothing active_stream_delegate(active_stream);
1946   active_stream->SetDelegate(&active_stream_delegate);
1947   base::WeakPtr<SpdyStream> created_stream = CreateStreamSynchronously(
1948       SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, NetLogWithSource());
1949   test::StreamDelegateDoNothing created_stream_delegate(created_stream);
1950   created_stream->SetDelegate(&created_stream_delegate);
1951 
1952   // The third will block.
1953   TestCompletionCallback callback;
1954   SpdyStreamRequest stream_request;
1955   EXPECT_THAT(
1956       stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session, url,
1957                                   /*can_send_early=*/false, MEDIUM, SocketTag(),
1958                                   NetLogWithSource(), callback.callback(),
1959                                   TRAFFIC_ANNOTATION_FOR_TESTS),
1960       IsError(ERR_IO_PENDING));
1961 
1962   // Activate the first stream by sending data.
1963   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1964   active_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1965   base::RunLoop().RunUntilIdle();
1966 
1967   // The active stream should now have a stream ID.
1968   EXPECT_EQ(1u, active_stream->stream_id());
1969   EXPECT_EQ(spdy::kInvalidStreamId, created_stream->stream_id());
1970   EXPECT_TRUE(session->is_active());
1971   EXPECT_TRUE(session->IsAvailable());
1972 
1973   spdy_session_pool_->OnSSLConfigForServersChanged(
1974       {HostPortPair::FromURL(url)});
1975   base::RunLoop().RunUntilIdle();
1976 
1977   // The active stream is still alive, so the session is still active.
1978   ASSERT_TRUE(session);
1979   EXPECT_TRUE(session->is_active());
1980   ASSERT_TRUE(active_stream);
1981 
1982   // The session is no longer available.
1983   EXPECT_FALSE(session->IsAvailable());
1984   EXPECT_TRUE(session->IsGoingAway());
1985 
1986   // The pending and created stream are cancelled.
1987   // TODO(https://crbug.com/1213609): Ideally, this would be recoverable.
1988   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_CHANGED));
1989   EXPECT_THAT(created_stream_delegate.WaitForClose(),
1990               IsError(ERR_NETWORK_CHANGED));
1991 
1992   // Close the active stream.
1993   active_stream->Close();
1994   // TODO(https://crbug.com/982499): The invalidated session should be closed
1995   // after a RunUntilIdle(), but it is not.
1996 }
1997 
1998 // Tests the OnSSLConfigForServersChanged() method when there only pending
1999 // streams active.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChangedWithOnlyPendingStreams)2000 TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithOnlyPendingStreams) {
2001   // Set up a SpdySession that accepts no streams.
2002   SpdyTestUtil spdy_util;
2003   spdy::SettingsMap settings;
2004   settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 0;
2005   spdy::SpdySerializedFrame settings_frame =
2006       spdy_util.ConstructSpdySettings(settings);
2007   spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck();
2008 
2009   const MockConnect connect_data(SYNCHRONOUS, OK);
2010   const MockRead reads[] = {
2011       CreateMockRead(settings_frame),
2012       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2013   };
2014   const MockWrite writes[] = {
2015       CreateMockWrite(settings_ack),
2016   };
2017 
2018   StaticSocketDataProvider socket_data(reads, writes);
2019   socket_data.set_connect_data(connect_data);
2020   session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
2021   AddSSLSocketData();
2022 
2023   CreateNetworkSession();
2024 
2025   const GURL url(kDefaultUrl);
2026   SpdySessionKey key(HostPortPair::FromURL(url), PRIVACY_MODE_DISABLED,
2027                      ProxyChain::Direct(), SessionUsage::kDestination,
2028                      SocketTag(), NetworkAnonymizationKey(),
2029                      SecureDnsPolicy::kAllow,
2030                      /*disable_cert_verification_network_fetches=*/false);
2031   base::WeakPtr<SpdySession> session =
2032       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
2033 
2034   // Pick up the SETTINGS frame to update SETTINGS_MAX_CONCURRENT_STREAMS.
2035   base::RunLoop().RunUntilIdle();
2036   EXPECT_EQ(0u, max_concurrent_streams(session));
2037 
2038   // Create a stream. It should block on the stream limit.
2039   TestCompletionCallback callback;
2040   SpdyStreamRequest stream_request;
2041   ASSERT_THAT(
2042       stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session, url,
2043                                   /*can_send_early=*/false, MEDIUM, SocketTag(),
2044                                   NetLogWithSource(), callback.callback(),
2045                                   TRAFFIC_ANNOTATION_FOR_TESTS),
2046       IsError(ERR_IO_PENDING));
2047 
2048   spdy_session_pool_->OnSSLConfigForServersChanged(
2049       {HostPortPair::FromURL(url)});
2050   base::RunLoop().RunUntilIdle();
2051 
2052   // The pending stream is cancelled.
2053   // TODO(https://crbug.com/1213609): Ideally, this would be recoverable.
2054   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_CHANGED));
2055   EXPECT_FALSE(session);
2056 }
2057 
2058 }  // namespace net
2059