• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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/http/http_stream_pool_group.h"
6 
7 #include <memory>
8 
9 #include "base/functional/callback_helpers.h"
10 #include "base/test/scoped_feature_list.h"
11 #include "base/test/task_environment.h"
12 #include "net/base/address_list.h"
13 #include "net/base/completion_once_callback.h"
14 #include "net/base/ip_address.h"
15 #include "net/base/network_anonymization_key.h"
16 #include "net/base/network_change_notifier.h"
17 #include "net/base/privacy_mode.h"
18 #include "net/http/http_network_session.h"
19 #include "net/http/http_stream.h"
20 #include "net/http/http_stream_pool.h"
21 #include "net/http/http_stream_pool_test_util.h"
22 #include "net/log/net_log.h"
23 #include "net/socket/socket_test_util.h"
24 #include "net/socket/stream_socket.h"
25 #include "net/spdy/spdy_test_util_common.h"
26 #include "net/test/gtest_util.h"
27 #include "net/test/test_with_task_environment.h"
28 #include "url/scheme_host_port.h"
29 
30 namespace net {
31 
32 using test::IsOk;
33 
34 using Group = HttpStreamPool::Group;
35 
36 class HttpStreamPoolGroupTest : public TestWithTaskEnvironment {
37  public:
HttpStreamPoolGroupTest()38   HttpStreamPoolGroupTest()
39       : TestWithTaskEnvironment(
40             base::test::TaskEnvironment::TimeSource::MOCK_TIME),
41         default_test_key_(url::SchemeHostPort("http", "a.test", 80),
42                           PRIVACY_MODE_DISABLED,
43                           SocketTag(),
44                           NetworkAnonymizationKey(),
45                           SecureDnsPolicy::kAllow,
46                           /*disable_cert_network_fetches=*/false) {
47     feature_list_.InitAndEnableFeature(features::kHappyEyeballsV3);
48     session_deps_.ignore_ip_address_changes = false;
49     session_deps_.disable_idle_sockets_close_on_memory_pressure = false;
50     InitializePool();
51   }
52 
53  protected:
set_ignore_ip_address_changes(bool ignore_ip_address_changes)54   void set_ignore_ip_address_changes(bool ignore_ip_address_changes) {
55     session_deps_.ignore_ip_address_changes = ignore_ip_address_changes;
56   }
57 
set_disable_idle_sockets_close_on_memory_pressure(bool disable_idle_sockets_close_on_memory_pressure)58   void set_disable_idle_sockets_close_on_memory_pressure(
59       bool disable_idle_sockets_close_on_memory_pressure) {
60     session_deps_.disable_idle_sockets_close_on_memory_pressure =
61         disable_idle_sockets_close_on_memory_pressure;
62   }
63 
set_enable_quic(bool enable_quic)64   void set_enable_quic(bool enable_quic) {
65     session_deps_.enable_quic = enable_quic;
66   }
67 
InitializePool()68   void InitializePool() {
69     http_network_session_ =
70         SpdySessionDependencies::SpdyCreateSession(&session_deps_);
71   }
72 
GetOrCreateTestGroup()73   Group& GetOrCreateTestGroup() {
74     return pool().GetOrCreateGroupForTesting(default_test_key_);
75   }
76 
GetTestGroup()77   Group* GetTestGroup() { return pool().GetGroupForTesting(default_test_key_); }
78 
pool()79   HttpStreamPool& pool() { return *http_network_session_->http_stream_pool(); }
80 
DestroyHttpNetworkSession()81   void DestroyHttpNetworkSession() { http_network_session_.reset(); }
82 
83  private:
84   base::test::ScopedFeatureList feature_list_;
85   const HttpStreamKey default_test_key_;
86   // For creating HttpNetworkSession.
87   SpdySessionDependencies session_deps_;
88   std::unique_ptr<HttpNetworkSession> http_network_session_;
89 };
90 
TEST_F(HttpStreamPoolGroupTest,CreateTextBasedStream)91 TEST_F(HttpStreamPoolGroupTest, CreateTextBasedStream) {
92   auto stream_socket = std::make_unique<FakeStreamSocket>();
93 
94   Group& group = GetOrCreateTestGroup();
95   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
96       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
97       LoadTimingInfo::ConnectTiming());
98   CHECK(stream);
99   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
100   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
101   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
102 }
103 
TEST_F(HttpStreamPoolGroupTest,ReleaseStreamSocketUnused)104 TEST_F(HttpStreamPoolGroupTest, ReleaseStreamSocketUnused) {
105   auto stream_socket = std::make_unique<FakeStreamSocket>();
106 
107   Group& group = GetOrCreateTestGroup();
108   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
109       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
110       LoadTimingInfo::ConnectTiming());
111   CHECK(stream);
112 
113   stream.reset();
114   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
115   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
116   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
117 
118   FastForwardBy(Group::kUnusedIdleStreamSocketTimeout);
119   group.CleanupTimedoutIdleStreamSocketsForTesting();
120   ASSERT_EQ(group.ActiveStreamSocketCount(), 0u);
121   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
122   ASSERT_EQ(pool().TotalActiveStreamCount(), 0u);
123 }
124 
TEST_F(HttpStreamPoolGroupTest,ReleaseStreamSocketUsed)125 TEST_F(HttpStreamPoolGroupTest, ReleaseStreamSocketUsed) {
126   auto stream_socket = std::make_unique<FakeStreamSocket>();
127   stream_socket->set_was_ever_used(true);
128 
129   Group& group = GetOrCreateTestGroup();
130   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
131       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
132       LoadTimingInfo::ConnectTiming());
133   CHECK(stream);
134 
135   stream.reset();
136   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
137   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
138   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
139 
140   static_assert(Group::kUnusedIdleStreamSocketTimeout <=
141                 Group::kUsedIdleStreamSocketTimeout);
142 
143   FastForwardBy(Group::kUnusedIdleStreamSocketTimeout);
144   group.CleanupTimedoutIdleStreamSocketsForTesting();
145   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
146   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
147   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
148 
149   FastForwardBy(Group::kUsedIdleStreamSocketTimeout);
150   group.CleanupTimedoutIdleStreamSocketsForTesting();
151   ASSERT_EQ(group.ActiveStreamSocketCount(), 0u);
152   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
153   ASSERT_EQ(pool().TotalActiveStreamCount(), 0u);
154 }
155 
TEST_F(HttpStreamPoolGroupTest,ReleaseStreamSocketNotIdle)156 TEST_F(HttpStreamPoolGroupTest, ReleaseStreamSocketNotIdle) {
157   auto stream_socket = std::make_unique<FakeStreamSocket>();
158   stream_socket->set_is_idle(false);
159 
160   Group& group = GetOrCreateTestGroup();
161   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
162       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
163       LoadTimingInfo::ConnectTiming());
164   CHECK(stream);
165 
166   stream.reset();
167 
168   ASSERT_FALSE(GetTestGroup());
169 }
170 
TEST_F(HttpStreamPoolGroupTest,IdleSocketDisconnected)171 TEST_F(HttpStreamPoolGroupTest, IdleSocketDisconnected) {
172   auto stream_socket = std::make_unique<FakeStreamSocket>();
173   FakeStreamSocket* raw_stream_socket = stream_socket.get();
174 
175   Group& group = GetOrCreateTestGroup();
176   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
177       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
178       LoadTimingInfo::ConnectTiming());
179   CHECK(stream);
180 
181   stream.reset();
182   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
183   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
184   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
185 
186   raw_stream_socket->set_is_connected(false);
187   group.CleanupTimedoutIdleStreamSocketsForTesting();
188   ASSERT_EQ(group.ActiveStreamSocketCount(), 0u);
189   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
190 }
191 
TEST_F(HttpStreamPoolGroupTest,IdleSocketReceivedDataUnexpectedly)192 TEST_F(HttpStreamPoolGroupTest, IdleSocketReceivedDataUnexpectedly) {
193   auto stream_socket = std::make_unique<FakeStreamSocket>();
194   FakeStreamSocket* raw_stream_socket = stream_socket.get();
195 
196   Group& group = GetOrCreateTestGroup();
197   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
198       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
199       LoadTimingInfo::ConnectTiming());
200   CHECK(stream);
201 
202   stream.reset();
203   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
204   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
205   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
206 
207   // Simulate the socket was used and not idle (received data).
208   raw_stream_socket->set_was_ever_used(true);
209   raw_stream_socket->set_is_idle(false);
210 
211   group.CleanupTimedoutIdleStreamSocketsForTesting();
212   ASSERT_EQ(group.ActiveStreamSocketCount(), 0u);
213   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
214 }
215 
TEST_F(HttpStreamPoolGroupTest,GetIdleStreamSocket)216 TEST_F(HttpStreamPoolGroupTest, GetIdleStreamSocket) {
217   Group& group = GetOrCreateTestGroup();
218   ASSERT_FALSE(group.GetIdleStreamSocket());
219 
220   auto stream_socket = std::make_unique<FakeStreamSocket>();
221   group.AddIdleStreamSocket(std::move(stream_socket));
222   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
223 
224   std::unique_ptr<StreamSocket> socket = group.GetIdleStreamSocket();
225   ASSERT_TRUE(socket);
226   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
227 }
228 
TEST_F(HttpStreamPoolGroupTest,GetIdleStreamSocketPreferUsed)229 TEST_F(HttpStreamPoolGroupTest, GetIdleStreamSocketPreferUsed) {
230   Group& group = GetOrCreateTestGroup();
231 
232   // Add 3 idle streams. the first and the third ones are marked as used.
233   auto stream_socket1 = std::make_unique<FakeStreamSocket>();
234   auto stream_socket2 = std::make_unique<FakeStreamSocket>();
235   auto stream_socket3 = std::make_unique<FakeStreamSocket>();
236 
237   stream_socket1->set_was_ever_used(true);
238   stream_socket3->set_was_ever_used(true);
239 
240   stream_socket1->set_peer_addr(IPEndPoint(IPAddress(192, 0, 2, 1), 80));
241   stream_socket2->set_peer_addr(IPEndPoint(IPAddress(192, 0, 2, 2), 80));
242   stream_socket3->set_peer_addr(IPEndPoint(IPAddress(192, 0, 2, 3), 80));
243 
244   group.AddIdleStreamSocket(std::move(stream_socket1));
245   group.AddIdleStreamSocket(std::move(stream_socket2));
246   group.AddIdleStreamSocket(std::move(stream_socket3));
247   ASSERT_EQ(group.IdleStreamSocketCount(), 3u);
248 
249   std::unique_ptr<StreamSocket> socket = group.GetIdleStreamSocket();
250   ASSERT_TRUE(socket);
251   ASSERT_EQ(group.IdleStreamSocketCount(), 2u);
252 
253   IPEndPoint peer;
254   int rv = socket->GetPeerAddress(&peer);
255   EXPECT_THAT(rv, IsOk());
256   EXPECT_THAT(peer, IPEndPoint(IPAddress(192, 0, 2, 3), 80));
257 }
258 
TEST_F(HttpStreamPoolGroupTest,GetIdleStreamSocketDisconnectedDuringIdle)259 TEST_F(HttpStreamPoolGroupTest, GetIdleStreamSocketDisconnectedDuringIdle) {
260   Group& group = GetOrCreateTestGroup();
261   ASSERT_FALSE(group.GetIdleStreamSocket());
262 
263   auto stream_socket = std::make_unique<FakeStreamSocket>();
264   FakeStreamSocket* raw_stream_socket = stream_socket.get();
265   group.AddIdleStreamSocket(std::move(stream_socket));
266   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
267 
268   raw_stream_socket->set_is_connected(false);
269   ASSERT_FALSE(group.GetIdleStreamSocket());
270   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
271 }
272 
TEST_F(HttpStreamPoolGroupTest,GetIdleStreamSocketUsedSocketDisconnected)273 TEST_F(HttpStreamPoolGroupTest, GetIdleStreamSocketUsedSocketDisconnected) {
274   Group& group = GetOrCreateTestGroup();
275   ASSERT_FALSE(group.GetIdleStreamSocket());
276 
277   auto stream_socket = std::make_unique<FakeStreamSocket>();
278   FakeStreamSocket* raw_stream_socket = stream_socket.get();
279   group.AddIdleStreamSocket(std::move(stream_socket));
280   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
281 
282   raw_stream_socket->set_was_ever_used(true);
283   raw_stream_socket->set_is_connected(false);
284   ASSERT_FALSE(group.GetIdleStreamSocket());
285   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
286 }
287 
TEST_F(HttpStreamPoolGroupTest,GetIdleStreamSocketTimedout)288 TEST_F(HttpStreamPoolGroupTest, GetIdleStreamSocketTimedout) {
289   Group& group = GetOrCreateTestGroup();
290 
291   auto stream_socket = std::make_unique<FakeStreamSocket>();
292   group.AddIdleStreamSocket(std::move(stream_socket));
293   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
294 
295   FastForwardBy(HttpStreamPool::Group::kUnusedIdleStreamSocketTimeout);
296 
297   ASSERT_FALSE(group.GetIdleStreamSocket());
298   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
299 }
300 
301 // Test that a group is destroyed when closing an idle stream that is the last
302 // stream in the group.
TEST_F(HttpStreamPoolGroupTest,DestroyGroupAfterCloseOneIdleStream)303 TEST_F(HttpStreamPoolGroupTest, DestroyGroupAfterCloseOneIdleStream) {
304   Group& group = GetOrCreateTestGroup();
305 
306   auto stream_socket = std::make_unique<FakeStreamSocket>();
307   group.AddIdleStreamSocket(std::move(stream_socket));
308   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
309 
310   ASSERT_TRUE(group.CloseOneIdleStreamSocket());
311   FastForwardUntilNoTasksRemain();
312   ASSERT_FALSE(GetTestGroup());
313 }
314 
TEST_F(HttpStreamPoolGroupTest,IPAddressChangeCleanupIdleSocket)315 TEST_F(HttpStreamPoolGroupTest, IPAddressChangeCleanupIdleSocket) {
316   auto stream_socket = std::make_unique<FakeStreamSocket>();
317 
318   Group& group = GetOrCreateTestGroup();
319   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
320       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
321       LoadTimingInfo::ConnectTiming());
322   CHECK(stream);
323 
324   stream.reset();
325   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
326   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
327   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
328 
329   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
330   RunUntilIdle();
331 
332   group.CleanupTimedoutIdleStreamSocketsForTesting();
333   ASSERT_EQ(group.ActiveStreamSocketCount(), 0u);
334   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
335 }
336 
TEST_F(HttpStreamPoolGroupTest,IPAddressChangeReleaseStreamSocket)337 TEST_F(HttpStreamPoolGroupTest, IPAddressChangeReleaseStreamSocket) {
338   auto stream_socket = std::make_unique<FakeStreamSocket>();
339 
340   Group& group = GetOrCreateTestGroup();
341   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
342       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
343       LoadTimingInfo::ConnectTiming());
344   CHECK(stream);
345 
346   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
347   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
348   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
349 
350   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
351   RunUntilIdle();
352 
353   stream.reset();
354 
355   ASSERT_FALSE(GetTestGroup());
356 }
357 
TEST_F(HttpStreamPoolGroupTest,IPAddressChangeIgnored)358 TEST_F(HttpStreamPoolGroupTest, IPAddressChangeIgnored) {
359   set_ignore_ip_address_changes(true);
360   InitializePool();
361 
362   auto stream_socket = std::make_unique<FakeStreamSocket>();
363   Group& group = GetOrCreateTestGroup();
364   std::unique_ptr<HttpStream> stream = group.CreateTextBasedStream(
365       std::move(stream_socket), StreamSocketHandle::SocketReuseType::kUnused,
366       LoadTimingInfo::ConnectTiming());
367   CHECK(stream);
368 
369   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
370   ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
371   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
372 
373   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
374   RunUntilIdle();
375 
376   stream.reset();
377 
378   group.CleanupTimedoutIdleStreamSocketsForTesting();
379   ASSERT_EQ(group.ActiveStreamSocketCount(), 1u);
380   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
381   ASSERT_EQ(pool().TotalActiveStreamCount(), 1u);
382 }
383 
TEST_F(HttpStreamPoolGroupTest,FlushIdleStreamsOnMemoryPressure)384 TEST_F(HttpStreamPoolGroupTest, FlushIdleStreamsOnMemoryPressure) {
385   set_disable_idle_sockets_close_on_memory_pressure(false);
386   InitializePool();
387 
388   {
389     Group& group = GetOrCreateTestGroup();
390     ASSERT_FALSE(group.GetIdleStreamSocket());
391 
392     group.AddIdleStreamSocket(std::make_unique<FakeStreamSocket>());
393     ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
394 
395     // Idle sockets should be flushed on moderate memory pressure and `group`
396     // should be destroyed.
397     base::MemoryPressureListener::NotifyMemoryPressure(
398         base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
399     FastForwardUntilNoTasksRemain();
400     ASSERT_FALSE(GetTestGroup());
401   }
402 
403   {
404     Group& group = GetOrCreateTestGroup();
405     group.AddIdleStreamSocket(std::make_unique<FakeStreamSocket>());
406     ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
407 
408     // Idle sockets should be flushed on critical memory pressure and `group`
409     // should be destroyed.
410     base::MemoryPressureListener::NotifyMemoryPressure(
411         base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
412     FastForwardUntilNoTasksRemain();
413     ASSERT_FALSE(GetTestGroup());
414   }
415 }
416 
TEST_F(HttpStreamPoolGroupTest,MemoryPressureDisabled)417 TEST_F(HttpStreamPoolGroupTest, MemoryPressureDisabled) {
418   set_disable_idle_sockets_close_on_memory_pressure(true);
419   InitializePool();
420 
421   Group& group = GetOrCreateTestGroup();
422   ASSERT_FALSE(group.GetIdleStreamSocket());
423 
424   group.AddIdleStreamSocket(std::make_unique<FakeStreamSocket>());
425   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
426 
427   // Idle sockets should be not flushed on moderate memory pressure.
428   base::MemoryPressureListener::NotifyMemoryPressure(
429       base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
430   base::RunLoop().RunUntilIdle();
431   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
432 
433   // Idle sockets should be not flushed on critical memory pressure.
434   base::MemoryPressureListener::NotifyMemoryPressure(
435       base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
436   base::RunLoop().RunUntilIdle();
437   ASSERT_EQ(group.IdleStreamSocketCount(), 1u);
438 }
439 
TEST_F(HttpStreamPoolGroupTest,DestroySessionWhileStreamAlive)440 TEST_F(HttpStreamPoolGroupTest, DestroySessionWhileStreamAlive) {
441   std::unique_ptr<HttpStream> stream =
442       GetOrCreateTestGroup().CreateTextBasedStream(
443           std::make_unique<FakeStreamSocket>(),
444           StreamSocketHandle::SocketReuseType::kUnused,
445           LoadTimingInfo::ConnectTiming());
446   CHECK(stream);
447 
448   // Destroy the session. This should not cause a crash.
449   DestroyHttpNetworkSession();
450 }
451 
TEST_F(HttpStreamPoolGroupTest,EnableDisableQuic)452 TEST_F(HttpStreamPoolGroupTest, EnableDisableQuic) {
453   const url::SchemeHostPort kHost("https", "www.example.com", 443);
454 
455   set_enable_quic(true);
456   InitializePool();
457   ASSERT_TRUE(pool().CanUseQuic(kHost, NetworkAnonymizationKey(),
458                                 /*enable_ip_based_pooling=*/true,
459                                 /*enable_alternative_services=*/true));
460 
461   set_enable_quic(false);
462   InitializePool();
463   ASSERT_FALSE(pool().CanUseQuic(kHost, NetworkAnonymizationKey(),
464                                  /*enable_ip_based_pooling=*/true,
465                                  /*enable_alternative_services=*/true));
466 }
467 
468 }  // namespace net
469