1 // Copyright 2012 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 // This file contains some tests for TCPClientSocket.
6 // transport_client_socket_unittest.cc contans some other tests that
7 // are common for TCP and other types of sockets.
8
9 #include "net/socket/tcp_client_socket.h"
10
11 #include <stddef.h>
12
13 #include <set>
14 #include <string>
15 #include <vector>
16
17 #include "base/strings/string_number_conversions.h"
18 #include "base/test/bind.h"
19 #include "base/test/power_monitor_test.h"
20 #include "base/test/scoped_feature_list.h"
21 #include "base/test/task_environment.h"
22 #include "build/build_config.h"
23 #include "net/base/features.h"
24 #include "net/base/ip_address.h"
25 #include "net/base/ip_endpoint.h"
26 #include "net/base/net_errors.h"
27 #include "net/base/test_completion_callback.h"
28 #include "net/log/net_log_source.h"
29 #include "net/nqe/network_quality_estimator_test_util.h"
30 #include "net/socket/socket_performance_watcher.h"
31 #include "net/socket/socket_test_util.h"
32 #include "net/socket/tcp_server_socket.h"
33 #include "net/test/embedded_test_server/embedded_test_server.h"
34 #include "net/test/gtest_util.h"
35 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 // This matches logic in tcp_client_socket.cc. Only used once, but defining it
40 // in this file instead of just inlining the OS checks where its used makes it
41 // more grep-able.
42 #if !BUILDFLAG(IS_ANDROID)
43 #define TCP_CLIENT_SOCKET_OBSERVES_SUSPEND
44 #endif
45
46 using net::test::IsError;
47 using net::test::IsOk;
48 using testing::Not;
49
50 namespace base {
51 class TimeDelta;
52 }
53
54 namespace net {
55
56 namespace {
57
58 class TCPClientSocketTest
59 : public testing::Test,
60 // The param indicates whether the
61 // "TcpSocketIoCompletionPortWin" feature is enabled.
62 public testing::WithParamInterface<bool> {
63 public:
TCPClientSocketTest()64 TCPClientSocketTest()
65 : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {
66 #if BUILDFLAG(IS_WIN)
67 scoped_feature_list_.InitWithFeatureState(
68 features::kTcpSocketIoCompletionPortWin, GetParam());
69 #else
70 CHECK(!GetParam());
71 #endif // BUILDFLAG(IS_WIN)
72 }
73
~TCPClientSocketTest()74 ~TCPClientSocketTest() override {
75 base::PowerMonitor::GetInstance()->ShutdownForTesting();
76 }
77
Suspend()78 void Suspend() { power_monitor_source_.Suspend(); }
Resume()79 void Resume() { power_monitor_source_.Resume(); }
80
CreateConnectedSockets(std::unique_ptr<StreamSocket> * accepted_socket,std::unique_ptr<TCPClientSocket> * client_socket,std::unique_ptr<ServerSocket> * server_socket_opt=nullptr)81 void CreateConnectedSockets(
82 std::unique_ptr<StreamSocket>* accepted_socket,
83 std::unique_ptr<TCPClientSocket>* client_socket,
84 std::unique_ptr<ServerSocket>* server_socket_opt = nullptr) {
85 IPAddress local_address = IPAddress::IPv4Localhost();
86
87 std::unique_ptr<TCPServerSocket> server_socket =
88 std::make_unique<TCPServerSocket>(nullptr, NetLogSource());
89 ASSERT_THAT(server_socket->Listen(IPEndPoint(local_address, 0), 1,
90 /*ipv6_only=*/std::nullopt),
91 IsOk());
92 IPEndPoint server_address;
93 ASSERT_THAT(server_socket->GetLocalAddress(&server_address), IsOk());
94
95 *client_socket = std::make_unique<TCPClientSocket>(
96 AddressList(server_address), nullptr, nullptr, nullptr, NetLogSource());
97
98 EXPECT_THAT((*client_socket)->Bind(IPEndPoint(local_address, 0)), IsOk());
99
100 IPEndPoint local_address_result;
101 EXPECT_THAT((*client_socket)->GetLocalAddress(&local_address_result),
102 IsOk());
103 EXPECT_EQ(local_address, local_address_result.address());
104
105 TestCompletionCallback connect_callback;
106 int connect_result = (*client_socket)->Connect(connect_callback.callback());
107
108 TestCompletionCallback accept_callback;
109 int result =
110 server_socket->Accept(accepted_socket, accept_callback.callback());
111 result = accept_callback.GetResult(result);
112 ASSERT_THAT(result, IsOk());
113
114 ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
115
116 EXPECT_TRUE((*client_socket)->IsConnected());
117 EXPECT_TRUE((*accepted_socket)->IsConnected());
118 if (server_socket_opt)
119 *server_socket_opt = std::move(server_socket);
120 }
121
122 private:
123 base::test::ScopedFeatureList scoped_feature_list_;
124 base::test::TaskEnvironment task_environment_;
125 base::test::ScopedPowerMonitorTestSource power_monitor_source_;
126 };
127
128 // Try binding a socket to loopback interface and verify that we can
129 // still connect to a server on the same interface.
TEST_P(TCPClientSocketTest,BindLoopbackToLoopback)130 TEST_P(TCPClientSocketTest, BindLoopbackToLoopback) {
131 IPAddress lo_address = IPAddress::IPv4Localhost();
132
133 TCPServerSocket server(nullptr, NetLogSource());
134 ASSERT_THAT(server.Listen(IPEndPoint(lo_address, 0), 1,
135 /*ipv6_only=*/std::nullopt),
136 IsOk());
137 IPEndPoint server_address;
138 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
139
140 TCPClientSocket socket(AddressList(server_address), nullptr, nullptr, nullptr,
141 NetLogSource());
142
143 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
144
145 IPEndPoint local_address_result;
146 EXPECT_THAT(socket.GetLocalAddress(&local_address_result), IsOk());
147 EXPECT_EQ(lo_address, local_address_result.address());
148
149 TestCompletionCallback connect_callback;
150 int connect_result = socket.Connect(connect_callback.callback());
151
152 TestCompletionCallback accept_callback;
153 std::unique_ptr<StreamSocket> accepted_socket;
154 int result = server.Accept(&accepted_socket, accept_callback.callback());
155 result = accept_callback.GetResult(result);
156 ASSERT_THAT(result, IsOk());
157
158 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
159
160 EXPECT_TRUE(socket.IsConnected());
161 socket.Disconnect();
162 EXPECT_FALSE(socket.IsConnected());
163 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED,
164 socket.GetLocalAddress(&local_address_result));
165 }
166
167 // Try to bind socket to the loopback interface and connect to an
168 // external address, verify that connection fails.
TEST_P(TCPClientSocketTest,BindLoopbackToExternal)169 TEST_P(TCPClientSocketTest, BindLoopbackToExternal) {
170 IPAddress external_ip(72, 14, 213, 105);
171 TCPClientSocket socket(AddressList::CreateFromIPAddress(external_ip, 80),
172 nullptr, nullptr, nullptr, NetLogSource());
173
174 EXPECT_THAT(socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)), IsOk());
175
176 TestCompletionCallback connect_callback;
177 int result = socket.Connect(connect_callback.callback());
178
179 // We may get different errors here on different system, but
180 // connect() is not expected to succeed.
181 EXPECT_THAT(connect_callback.GetResult(result), Not(IsOk()));
182 }
183
184 // Bind a socket to the IPv4 loopback interface and try to connect to
185 // the IPv6 loopback interface, verify that connection fails.
TEST_P(TCPClientSocketTest,BindLoopbackToIPv6)186 TEST_P(TCPClientSocketTest, BindLoopbackToIPv6) {
187 TCPServerSocket server(nullptr, NetLogSource());
188 int listen_result =
189 server.Listen(IPEndPoint(IPAddress::IPv6Localhost(), 0), 1,
190 /*ipv6_only=*/std::nullopt);
191 if (listen_result != OK) {
192 LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is disabled."
193 " Skipping the test";
194 return;
195 }
196
197 IPEndPoint server_address;
198 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
199 TCPClientSocket socket(AddressList(server_address), nullptr, nullptr, nullptr,
200 NetLogSource());
201
202 EXPECT_THAT(socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)), IsOk());
203
204 TestCompletionCallback connect_callback;
205 int result = socket.Connect(connect_callback.callback());
206
207 EXPECT_THAT(connect_callback.GetResult(result), Not(IsOk()));
208 }
209
TEST_P(TCPClientSocketTest,WasEverUsed)210 TEST_P(TCPClientSocketTest, WasEverUsed) {
211 IPAddress lo_address = IPAddress::IPv4Localhost();
212 TCPServerSocket server(nullptr, NetLogSource());
213 ASSERT_THAT(
214 server.Listen(IPEndPoint(lo_address, 0), 1, /*ipv6_only=*/std::nullopt),
215 IsOk());
216 IPEndPoint server_address;
217 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
218
219 TCPClientSocket socket(AddressList(server_address), nullptr, nullptr, nullptr,
220 NetLogSource());
221
222 EXPECT_FALSE(socket.WasEverUsed());
223
224 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
225
226 // Just connecting the socket should not set WasEverUsed.
227 TestCompletionCallback connect_callback;
228 int connect_result = socket.Connect(connect_callback.callback());
229 EXPECT_FALSE(socket.WasEverUsed());
230
231 TestCompletionCallback accept_callback;
232 std::unique_ptr<StreamSocket> accepted_socket;
233 int result = server.Accept(&accepted_socket, accept_callback.callback());
234 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
235 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
236
237 EXPECT_FALSE(socket.WasEverUsed());
238 EXPECT_TRUE(socket.IsConnected());
239
240 // Writing some data to the socket _should_ set WasEverUsed.
241 const char kRequest[] = "GET / HTTP/1.0";
242 auto write_buffer = base::MakeRefCounted<StringIOBuffer>(kRequest);
243 TestCompletionCallback write_callback;
244 result =
245 socket.Write(write_buffer.get(), write_buffer->size(),
246 write_callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
247 write_callback.GetResult(result);
248 EXPECT_TRUE(socket.WasEverUsed());
249 socket.Disconnect();
250 EXPECT_FALSE(socket.IsConnected());
251
252 EXPECT_TRUE(socket.WasEverUsed());
253
254 // Re-use the socket, which should set WasEverUsed to false.
255 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
256 TestCompletionCallback connect_callback2;
257 connect_result = socket.Connect(connect_callback2.callback());
258 EXPECT_FALSE(socket.WasEverUsed());
259 }
260
261 // Tests that DNS aliases can be stored in a socket for reuse.
TEST_P(TCPClientSocketTest,DnsAliasesPersistForReuse)262 TEST_P(TCPClientSocketTest, DnsAliasesPersistForReuse) {
263 IPAddress lo_address = IPAddress::IPv4Localhost();
264 TCPServerSocket server(nullptr, NetLogSource());
265 ASSERT_THAT(
266 server.Listen(IPEndPoint(lo_address, 0), 1, /*ipv6_only=*/std::nullopt),
267 IsOk());
268 IPEndPoint server_address;
269 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
270
271 // Create a socket.
272 TCPClientSocket socket(AddressList(server_address), nullptr, nullptr, nullptr,
273 NetLogSource());
274 EXPECT_FALSE(socket.WasEverUsed());
275 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
276
277 // The socket's DNS aliases are unset.
278 EXPECT_TRUE(socket.GetDnsAliases().empty());
279
280 // Set the aliases.
281 std::set<std::string> dns_aliases({"alias1", "alias2", "host"});
282 socket.SetDnsAliases(dns_aliases);
283
284 // Verify that the aliases are set.
285 EXPECT_THAT(socket.GetDnsAliases(),
286 testing::UnorderedElementsAre("alias1", "alias2", "host"));
287
288 // Connect the socket.
289 TestCompletionCallback connect_callback;
290 int connect_result = socket.Connect(connect_callback.callback());
291 EXPECT_FALSE(socket.WasEverUsed());
292 TestCompletionCallback accept_callback;
293 std::unique_ptr<StreamSocket> accepted_socket;
294 int result = server.Accept(&accepted_socket, accept_callback.callback());
295 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
296 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
297 EXPECT_FALSE(socket.WasEverUsed());
298 EXPECT_TRUE(socket.IsConnected());
299
300 // Write some data to the socket to set WasEverUsed, so that the
301 // socket can be re-used.
302 const char kRequest[] = "GET / HTTP/1.0";
303 auto write_buffer = base::MakeRefCounted<StringIOBuffer>(kRequest);
304 TestCompletionCallback write_callback;
305 result =
306 socket.Write(write_buffer.get(), write_buffer->size(),
307 write_callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
308 write_callback.GetResult(result);
309 EXPECT_TRUE(socket.WasEverUsed());
310 socket.Disconnect();
311 EXPECT_FALSE(socket.IsConnected());
312 EXPECT_TRUE(socket.WasEverUsed());
313
314 // Re-use the socket, and verify that the aliases are still set.
315 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
316 TestCompletionCallback connect_callback2;
317 connect_result = socket.Connect(connect_callback2.callback());
318 EXPECT_FALSE(socket.WasEverUsed());
319 EXPECT_THAT(socket.GetDnsAliases(),
320 testing::ElementsAre("alias1", "alias2", "host"));
321 }
322
323 class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
324 public:
325 TestSocketPerformanceWatcher() = default;
326
327 TestSocketPerformanceWatcher(const TestSocketPerformanceWatcher&) = delete;
328 TestSocketPerformanceWatcher& operator=(const TestSocketPerformanceWatcher&) =
329 delete;
330
331 ~TestSocketPerformanceWatcher() override = default;
332
ShouldNotifyUpdatedRTT() const333 bool ShouldNotifyUpdatedRTT() const override { return true; }
334
OnUpdatedRTTAvailable(const base::TimeDelta & rtt)335 void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override {}
336
OnConnectionChanged()337 void OnConnectionChanged() override { connection_changed_count_++; }
338
connection_changed_count() const339 size_t connection_changed_count() const { return connection_changed_count_; }
340
341 private:
342 size_t connection_changed_count_ = 0u;
343 };
344
345 // TestSocketPerformanceWatcher requires kernel support for tcp_info struct, and
346 // so it is enabled only on certain platforms.
347 #if defined(TCP_INFO) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
348 #define MAYBE_TestSocketPerformanceWatcher TestSocketPerformanceWatcher
349 #else
350 #define MAYBE_TestSocketPerformanceWatcher TestSocketPerformanceWatcher
351 #endif
352 // Tests if the socket performance watcher is notified if the same socket is
353 // used for a different connection.
TEST_P(TCPClientSocketTest,MAYBE_TestSocketPerformanceWatcher)354 TEST_P(TCPClientSocketTest, MAYBE_TestSocketPerformanceWatcher) {
355 const size_t kNumIPs = 2;
356 IPAddressList ip_list;
357 for (size_t i = 0; i < kNumIPs; ++i)
358 ip_list.push_back(IPAddress(72, 14, 213, i));
359
360 auto watcher = std::make_unique<TestSocketPerformanceWatcher>();
361 TestSocketPerformanceWatcher* watcher_ptr = watcher.get();
362
363 std::vector<std::string> aliases({"example.com"});
364
365 TCPClientSocket socket(
366 AddressList::CreateFromIPAddressList(ip_list, std::move(aliases)),
367 std::move(watcher), nullptr, nullptr, NetLogSource());
368
369 EXPECT_THAT(socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)), IsOk());
370
371 TestCompletionCallback connect_callback;
372
373 ASSERT_NE(OK, connect_callback.GetResult(
374 socket.Connect(connect_callback.callback())));
375
376 EXPECT_EQ(kNumIPs - 1, watcher_ptr->connection_changed_count());
377 }
378
379 // On Android, where socket tagging is supported, verify that
380 // TCPClientSocket::Tag works as expected.
381 #if BUILDFLAG(IS_ANDROID)
TEST_P(TCPClientSocketTest,Tag)382 TEST_P(TCPClientSocketTest, Tag) {
383 if (!CanGetTaggedBytes()) {
384 DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
385 return;
386 }
387
388 // Start test server.
389 EmbeddedTestServer test_server;
390 test_server.AddDefaultHandlers(base::FilePath());
391 ASSERT_TRUE(test_server.Start());
392
393 AddressList addr_list;
394 ASSERT_TRUE(test_server.GetAddressList(&addr_list));
395 TCPClientSocket s(addr_list, nullptr, nullptr, nullptr, NetLogSource());
396
397 // Verify TCP connect packets are tagged and counted properly.
398 int32_t tag_val1 = 0x12345678;
399 uint64_t old_traffic = GetTaggedBytes(tag_val1);
400 SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
401 s.ApplySocketTag(tag1);
402 TestCompletionCallback connect_callback;
403 int connect_result = s.Connect(connect_callback.callback());
404 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
405 EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
406
407 // Verify socket can be retagged with a new value and the current process's
408 // UID.
409 int32_t tag_val2 = 0x87654321;
410 old_traffic = GetTaggedBytes(tag_val2);
411 SocketTag tag2(getuid(), tag_val2);
412 s.ApplySocketTag(tag2);
413 const char kRequest1[] = "GET / HTTP/1.0";
414 auto write_buffer1 = base::MakeRefCounted<StringIOBuffer>(kRequest1);
415 TestCompletionCallback write_callback1;
416 EXPECT_EQ(s.Write(write_buffer1.get(), strlen(kRequest1),
417 write_callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
418 static_cast<int>(strlen(kRequest1)));
419 EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
420
421 // Verify socket can be retagged with a new value and the current process's
422 // UID.
423 old_traffic = GetTaggedBytes(tag_val1);
424 s.ApplySocketTag(tag1);
425 const char kRequest2[] = "\n\n";
426 scoped_refptr<IOBufferWithSize> write_buffer2 =
427 base::MakeRefCounted<IOBufferWithSize>(strlen(kRequest2));
428 memmove(write_buffer2->data(), kRequest2, strlen(kRequest2));
429 TestCompletionCallback write_callback2;
430 EXPECT_EQ(s.Write(write_buffer2.get(), strlen(kRequest2),
431 write_callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
432 static_cast<int>(strlen(kRequest2)));
433 EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
434
435 s.Disconnect();
436 }
437
TEST_P(TCPClientSocketTest,TagAfterConnect)438 TEST_P(TCPClientSocketTest, TagAfterConnect) {
439 if (!CanGetTaggedBytes()) {
440 DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
441 return;
442 }
443
444 // Start test server.
445 EmbeddedTestServer test_server;
446 test_server.AddDefaultHandlers(base::FilePath());
447 ASSERT_TRUE(test_server.Start());
448
449 AddressList addr_list;
450 ASSERT_TRUE(test_server.GetAddressList(&addr_list));
451 TCPClientSocket s(addr_list, nullptr, nullptr, nullptr, NetLogSource());
452
453 // Connect socket.
454 TestCompletionCallback connect_callback;
455 int connect_result = s.Connect(connect_callback.callback());
456 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
457
458 // Verify socket can be tagged with a new value and the current process's
459 // UID.
460 int32_t tag_val2 = 0x87654321;
461 uint64_t old_traffic = GetTaggedBytes(tag_val2);
462 SocketTag tag2(getuid(), tag_val2);
463 s.ApplySocketTag(tag2);
464 const char kRequest1[] = "GET / HTTP/1.0";
465 auto write_buffer1 = base::MakeRefCounted<StringIOBuffer>(kRequest1);
466 TestCompletionCallback write_callback1;
467 EXPECT_EQ(s.Write(write_buffer1.get(), strlen(kRequest1),
468 write_callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
469 static_cast<int>(strlen(kRequest1)));
470 EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
471
472 // Verify socket can be retagged with a new value and the current process's
473 // UID.
474 int32_t tag_val1 = 0x12345678;
475 old_traffic = GetTaggedBytes(tag_val1);
476 SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
477 s.ApplySocketTag(tag1);
478 const char kRequest2[] = "\n\n";
479 auto write_buffer2 = base::MakeRefCounted<StringIOBuffer>(kRequest2);
480 TestCompletionCallback write_callback2;
481 EXPECT_EQ(s.Write(write_buffer2.get(), strlen(kRequest2),
482 write_callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
483 static_cast<int>(strlen(kRequest2)));
484 EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
485
486 s.Disconnect();
487 }
488 #endif // BUILDFLAG(IS_ANDROID)
489
490 // TCP socket that hangs indefinitely when establishing a connection.
491 class NeverConnectingTCPClientSocket : public TCPClientSocket {
492 public:
NeverConnectingTCPClientSocket(const AddressList & addresses,std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,NetworkQualityEstimator * network_quality_estimator,net::NetLog * net_log,const net::NetLogSource & source)493 NeverConnectingTCPClientSocket(
494 const AddressList& addresses,
495 std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
496 NetworkQualityEstimator* network_quality_estimator,
497 net::NetLog* net_log,
498 const net::NetLogSource& source)
499 : TCPClientSocket(addresses,
500 std::move(socket_performance_watcher),
501 network_quality_estimator,
502 net_log,
503 source) {}
504
505 // Returns the number of times that ConnectInternal() was called.
connect_internal_counter() const506 int connect_internal_counter() const { return connect_internal_counter_; }
507
508 private:
ConnectInternal(const IPEndPoint & endpoint)509 int ConnectInternal(const IPEndPoint& endpoint) override {
510 connect_internal_counter_++;
511 return ERR_IO_PENDING;
512 }
513
514 int connect_internal_counter_ = 0;
515 };
516
517 // Tests for closing sockets on suspend mode.
518 #if defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
519
520 // Entering suspend mode shouldn't affect sockets that haven't connected yet, or
521 // listening server sockets.
TEST_P(TCPClientSocketTest,SuspendBeforeConnect)522 TEST_P(TCPClientSocketTest, SuspendBeforeConnect) {
523 IPAddress lo_address = IPAddress::IPv4Localhost();
524
525 TCPServerSocket server(nullptr, NetLogSource());
526 ASSERT_THAT(
527 server.Listen(IPEndPoint(lo_address, 0), 1, /*ipv6_only=*/std::nullopt),
528 IsOk());
529 IPEndPoint server_address;
530 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
531
532 TCPClientSocket socket(AddressList(server_address), nullptr, nullptr, nullptr,
533 NetLogSource());
534
535 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
536
537 IPEndPoint local_address_result;
538 EXPECT_THAT(socket.GetLocalAddress(&local_address_result), IsOk());
539 EXPECT_EQ(lo_address, local_address_result.address());
540
541 TestCompletionCallback accept_callback;
542 std::unique_ptr<StreamSocket> accepted_socket;
543 ASSERT_THAT(server.Accept(&accepted_socket, accept_callback.callback()),
544 IsError(ERR_IO_PENDING));
545
546 Suspend();
547 // Power notifications happen asynchronously, so have to wait for the socket
548 // to be notified of the suspend event.
549 base::RunLoop().RunUntilIdle();
550
551 TestCompletionCallback connect_callback;
552 int connect_result = socket.Connect(connect_callback.callback());
553
554 ASSERT_THAT(accept_callback.WaitForResult(), IsOk());
555
556 ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
557
558 EXPECT_TRUE(socket.IsConnected());
559 EXPECT_TRUE(accepted_socket->IsConnected());
560 }
561
TEST_P(TCPClientSocketTest,SuspendDuringConnect)562 TEST_P(TCPClientSocketTest, SuspendDuringConnect) {
563 IPAddress lo_address = IPAddress::IPv4Localhost();
564
565 TCPServerSocket server(nullptr, NetLogSource());
566 ASSERT_THAT(
567 server.Listen(IPEndPoint(lo_address, 0), 1, /*ipv6_only=*/std::nullopt),
568 IsOk());
569 IPEndPoint server_address;
570 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
571
572 NeverConnectingTCPClientSocket socket(AddressList(server_address), nullptr,
573 nullptr, nullptr, NetLogSource());
574
575 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
576
577 IPEndPoint local_address_result;
578 EXPECT_THAT(socket.GetLocalAddress(&local_address_result), IsOk());
579 EXPECT_EQ(lo_address, local_address_result.address());
580
581 TestCompletionCallback connect_callback;
582 int rv = socket.Connect(connect_callback.callback());
583 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
584 Suspend();
585 EXPECT_THAT(connect_callback.WaitForResult(),
586 IsError(ERR_NETWORK_IO_SUSPENDED));
587 }
588
TEST_P(TCPClientSocketTest,SuspendDuringConnectMultipleAddresses)589 TEST_P(TCPClientSocketTest, SuspendDuringConnectMultipleAddresses) {
590 IPAddress lo_address = IPAddress::IPv4Localhost();
591
592 TCPServerSocket server(nullptr, NetLogSource());
593 ASSERT_THAT(server.Listen(IPEndPoint(IPAddress(0, 0, 0, 0), 0), 1,
594 /*ipv6_only=*/std::nullopt),
595 IsOk());
596 IPEndPoint server_address;
597 ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
598
599 AddressList address_list;
600 address_list.push_back(
601 IPEndPoint(IPAddress(127, 0, 0, 1), server_address.port()));
602 address_list.push_back(
603 IPEndPoint(IPAddress(127, 0, 0, 2), server_address.port()));
604 NeverConnectingTCPClientSocket socket(address_list, nullptr, nullptr, nullptr,
605 NetLogSource());
606
607 EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
608
609 IPEndPoint local_address_result;
610 EXPECT_THAT(socket.GetLocalAddress(&local_address_result), IsOk());
611 EXPECT_EQ(lo_address, local_address_result.address());
612
613 TestCompletionCallback connect_callback;
614 int rv = socket.Connect(connect_callback.callback());
615 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
616 Suspend();
617 EXPECT_THAT(connect_callback.WaitForResult(),
618 IsError(ERR_NETWORK_IO_SUSPENDED));
619 }
620
TEST_P(TCPClientSocketTest,SuspendWhileIdle)621 TEST_P(TCPClientSocketTest, SuspendWhileIdle) {
622 std::unique_ptr<StreamSocket> accepted_socket;
623 std::unique_ptr<TCPClientSocket> client_socket;
624 std::unique_ptr<ServerSocket> server_socket;
625 CreateConnectedSockets(&accepted_socket, &client_socket, &server_socket);
626
627 Suspend();
628 // Power notifications happen asynchronously.
629 base::RunLoop().RunUntilIdle();
630
631 auto buffer = base::MakeRefCounted<IOBufferWithSize>(1);
632 buffer->data()[0] = '1';
633 TestCompletionCallback callback;
634 // Check that the client socket is disconnected, and actions fail with
635 // ERR_NETWORK_IO_SUSPENDED.
636 EXPECT_FALSE(client_socket->IsConnected());
637 EXPECT_THAT(client_socket->Read(buffer.get(), 1, callback.callback()),
638 IsError(ERR_NETWORK_IO_SUSPENDED));
639 EXPECT_THAT(client_socket->Write(buffer.get(), 1, callback.callback(),
640 TRAFFIC_ANNOTATION_FOR_TESTS),
641 IsError(ERR_NETWORK_IO_SUSPENDED));
642
643 // Check that the accepted socket is disconnected, and actions fail with
644 // ERR_NETWORK_IO_SUSPENDED.
645 EXPECT_FALSE(accepted_socket->IsConnected());
646 EXPECT_THAT(accepted_socket->Read(buffer.get(), 1, callback.callback()),
647 IsError(ERR_NETWORK_IO_SUSPENDED));
648 EXPECT_THAT(accepted_socket->Write(buffer.get(), 1, callback.callback(),
649 TRAFFIC_ANNOTATION_FOR_TESTS),
650 IsError(ERR_NETWORK_IO_SUSPENDED));
651
652 // Reconnecting the socket should work.
653 TestCompletionCallback connect_callback;
654 int connect_result = client_socket->Connect(connect_callback.callback());
655 accepted_socket.reset();
656 TestCompletionCallback accept_callback;
657 int accept_result =
658 server_socket->Accept(&accepted_socket, accept_callback.callback());
659 ASSERT_THAT(accept_callback.GetResult(accept_result), IsOk());
660 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
661 }
662
TEST_P(TCPClientSocketTest,SuspendDuringRead)663 TEST_P(TCPClientSocketTest, SuspendDuringRead) {
664 std::unique_ptr<StreamSocket> accepted_socket;
665 std::unique_ptr<TCPClientSocket> client_socket;
666 CreateConnectedSockets(&accepted_socket, &client_socket);
667
668 // Start a read. This shouldn't complete, since the other end of the pipe
669 // writes no data.
670 auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(1);
671 read_buffer->data()[0] = '1';
672 TestCompletionCallback callback;
673 ASSERT_THAT(client_socket->Read(read_buffer.get(), 1, callback.callback()),
674 IsError(ERR_IO_PENDING));
675
676 // Simulate a suspend event. Can't use a real power event, as it would affect
677 // |accepted_socket| as well.
678 client_socket->OnSuspend();
679 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_IO_SUSPENDED));
680
681 // Check that the client socket really is disconnected.
682 EXPECT_FALSE(client_socket->IsConnected());
683 EXPECT_THAT(client_socket->Read(read_buffer.get(), 1, callback.callback()),
684 IsError(ERR_NETWORK_IO_SUSPENDED));
685 EXPECT_THAT(client_socket->Write(read_buffer.get(), 1, callback.callback(),
686 TRAFFIC_ANNOTATION_FOR_TESTS),
687 IsError(ERR_NETWORK_IO_SUSPENDED));
688 }
689
TEST_P(TCPClientSocketTest,SuspendDuringWrite)690 TEST_P(TCPClientSocketTest, SuspendDuringWrite) {
691 std::unique_ptr<StreamSocket> accepted_socket;
692 std::unique_ptr<TCPClientSocket> client_socket;
693 CreateConnectedSockets(&accepted_socket, &client_socket);
694
695 // Write to the socket until a write doesn't complete synchronously.
696 const int kBufferSize = 4096;
697 auto write_buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
698 memset(write_buffer->data(), '1', kBufferSize);
699 TestCompletionCallback callback;
700 while (true) {
701 int rv =
702 client_socket->Write(write_buffer.get(), kBufferSize,
703 callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
704 if (rv == ERR_IO_PENDING)
705 break;
706 ASSERT_GT(rv, 0);
707 }
708
709 // Simulate a suspend event. Can't use a real power event, as it would affect
710 // |accepted_socket| as well.
711 client_socket->OnSuspend();
712 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_IO_SUSPENDED));
713
714 // Check that the client socket really is disconnected.
715 EXPECT_FALSE(client_socket->IsConnected());
716 EXPECT_THAT(client_socket->Read(write_buffer.get(), 1, callback.callback()),
717 IsError(ERR_NETWORK_IO_SUSPENDED));
718 EXPECT_THAT(client_socket->Write(write_buffer.get(), 1, callback.callback(),
719 TRAFFIC_ANNOTATION_FOR_TESTS),
720 IsError(ERR_NETWORK_IO_SUSPENDED));
721 }
722
TEST_P(TCPClientSocketTest,SuspendDuringReadAndWrite)723 TEST_P(TCPClientSocketTest, SuspendDuringReadAndWrite) {
724 enum class ReadCallbackAction {
725 kNone,
726 kDestroySocket,
727 kDisconnectSocket,
728 kReconnectSocket,
729 };
730
731 for (ReadCallbackAction read_callback_action : {
732 ReadCallbackAction::kNone,
733 ReadCallbackAction::kDestroySocket,
734 ReadCallbackAction::kDisconnectSocket,
735 ReadCallbackAction::kReconnectSocket,
736 }) {
737 std::unique_ptr<StreamSocket> accepted_socket;
738 std::unique_ptr<TCPClientSocket> client_socket;
739 std::unique_ptr<ServerSocket> server_socket;
740 CreateConnectedSockets(&accepted_socket, &client_socket, &server_socket);
741
742 // Start a read. This shouldn't complete, since the other end of the pipe
743 // writes no data.
744 auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(1);
745 read_buffer->data()[0] = '1';
746 TestCompletionCallback read_callback;
747
748 // Used int the ReadCallbackAction::kReconnectSocket case, since can't run a
749 // nested message loop in the read callback.
750 TestCompletionCallback nested_connect_callback;
751 int nested_connect_result;
752
753 CompletionOnceCallback read_completion_once_callback =
754 base::BindLambdaForTesting([&](int result) {
755 EXPECT_FALSE(client_socket->IsConnected());
756 switch (read_callback_action) {
757 case ReadCallbackAction::kNone:
758 break;
759 case ReadCallbackAction::kDestroySocket:
760 client_socket.reset();
761 break;
762 case ReadCallbackAction::kDisconnectSocket:
763 client_socket->Disconnect();
764 break;
765 case ReadCallbackAction::kReconnectSocket: {
766 TestCompletionCallback connect_callback;
767 nested_connect_result =
768 client_socket->Connect(nested_connect_callback.callback());
769 break;
770 }
771 }
772 read_callback.callback().Run(result);
773 });
774 ASSERT_THAT(client_socket->Read(read_buffer.get(), 1,
775 std::move(read_completion_once_callback)),
776 IsError(ERR_IO_PENDING));
777
778 // Write to the socket until a write doesn't complete synchronously.
779 const int kBufferSize = 4096;
780 auto write_buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
781 memset(write_buffer->data(), '1', kBufferSize);
782 TestCompletionCallback write_callback;
783 while (true) {
784 int rv = client_socket->Write(write_buffer.get(), kBufferSize,
785 write_callback.callback(),
786 TRAFFIC_ANNOTATION_FOR_TESTS);
787 if (rv == ERR_IO_PENDING)
788 break;
789 ASSERT_GT(rv, 0);
790 }
791
792 // Simulate a suspend event. Can't use a real power event, as it would
793 // affect |accepted_socket| as well.
794 client_socket->OnSuspend();
795 EXPECT_THAT(read_callback.WaitForResult(),
796 IsError(ERR_NETWORK_IO_SUSPENDED));
797 if (read_callback_action == ReadCallbackAction::kNone) {
798 EXPECT_THAT(write_callback.WaitForResult(),
799 IsError(ERR_NETWORK_IO_SUSPENDED));
800
801 // Check that the client socket really is disconnected.
802 EXPECT_FALSE(client_socket->IsConnected());
803 EXPECT_THAT(
804 client_socket->Read(read_buffer.get(), 1, read_callback.callback()),
805 IsError(ERR_NETWORK_IO_SUSPENDED));
806 EXPECT_THAT(
807 client_socket->Write(write_buffer.get(), 1, write_callback.callback(),
808 TRAFFIC_ANNOTATION_FOR_TESTS),
809 IsError(ERR_NETWORK_IO_SUSPENDED));
810 } else {
811 // Each of the actions taken in the read callback will cancel the pending
812 // write callback.
813 EXPECT_FALSE(write_callback.have_result());
814 }
815
816 if (read_callback_action == ReadCallbackAction::kReconnectSocket) {
817 // Finish establishing a connection, just to make sure the reconnect case
818 // completely works.
819 accepted_socket.reset();
820 TestCompletionCallback accept_callback;
821 int accept_result =
822 server_socket->Accept(&accepted_socket, accept_callback.callback());
823 ASSERT_THAT(accept_callback.GetResult(accept_result), IsOk());
824 EXPECT_THAT(nested_connect_callback.GetResult(nested_connect_result),
825 IsOk());
826 }
827 }
828 }
829
830 #endif // defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
831
832 INSTANTIATE_TEST_SUITE_P(Any,
833 TCPClientSocketTest,
834 ::testing::Values(false
835 #if BUILDFLAG(IS_WIN)
836 ,
837 true
838 #endif
839 ),
__anon464c0e790302(::testing::TestParamInfo<bool> info) 840 [](::testing::TestParamInfo<bool> info) {
841 if (info.param) {
842 return "TcpSocketIoCompletionPortWin";
843 }
844 return "Base";
845 });
846
847 // Scoped helper to override the TCP connect attempt policy.
848 class OverrideTcpConnectAttemptTimeout {
849 public:
OverrideTcpConnectAttemptTimeout(double rtt_multipilier,base::TimeDelta min_timeout,base::TimeDelta max_timeout)850 OverrideTcpConnectAttemptTimeout(double rtt_multipilier,
851 base::TimeDelta min_timeout,
852 base::TimeDelta max_timeout) {
853 base::FieldTrialParams params;
854 params[features::kTimeoutTcpConnectAttemptRTTMultiplier.name] =
855 base::NumberToString(rtt_multipilier);
856 params[features::kTimeoutTcpConnectAttemptMin.name] =
857 base::NumberToString(min_timeout.InMilliseconds()) + "ms";
858 params[features::kTimeoutTcpConnectAttemptMax.name] =
859 base::NumberToString(max_timeout.InMilliseconds()) + "ms";
860
861 scoped_feature_list_.InitAndEnableFeatureWithParameters(
862 features::kTimeoutTcpConnectAttempt, params);
863 }
864
865 private:
866 base::test::ScopedFeatureList scoped_feature_list_;
867 };
868
869 // Test fixture that uses a MOCK_TIME test environment, so time can
870 // be advanced programmatically.
871 class TCPClientSocketMockTimeTest : public testing::Test {
872 public:
TCPClientSocketMockTimeTest()873 TCPClientSocketMockTimeTest()
874 : task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
875 base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
876
877 protected:
878 base::test::TaskEnvironment task_environment_;
879 };
880
881 // Tests that no TCP connect timeout is enforced by default (i.e.
882 // when the feature is disabled).
TEST_F(TCPClientSocketMockTimeTest,NoConnectAttemptTimeoutByDefault)883 TEST_F(TCPClientSocketMockTimeTest, NoConnectAttemptTimeoutByDefault) {
884 IPEndPoint server_address(IPAddress::IPv4Localhost(), 80);
885 NeverConnectingTCPClientSocket socket(AddressList(server_address), nullptr,
886 nullptr, nullptr, NetLogSource());
887
888 TestCompletionCallback connect_callback;
889 int rv = socket.Connect(connect_callback.callback());
890 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
891
892 // After 4 minutes, the socket should still be connecting.
893 task_environment_.FastForwardBy(base::Minutes(4));
894 EXPECT_FALSE(connect_callback.have_result());
895 EXPECT_FALSE(socket.IsConnected());
896
897 // 1 attempt was made.
898 EXPECT_EQ(1, socket.connect_internal_counter());
899 }
900
901 // Tests that the maximum timeout is used when there is no estimated
902 // RTT.
TEST_F(TCPClientSocketMockTimeTest,ConnectAttemptTimeoutUsesMaxWhenNoRTT)903 TEST_F(TCPClientSocketMockTimeTest, ConnectAttemptTimeoutUsesMaxWhenNoRTT) {
904 OverrideTcpConnectAttemptTimeout override_timeout(1, base::Seconds(4),
905 base::Seconds(10));
906
907 IPEndPoint server_address(IPAddress::IPv4Localhost(), 80);
908
909 // Pass a null NetworkQualityEstimator, so the TCPClientSocket is unable to
910 // estimate the RTT.
911 NeverConnectingTCPClientSocket socket(AddressList(server_address), nullptr,
912 nullptr, nullptr, NetLogSource());
913
914 // Start connecting.
915 TestCompletionCallback connect_callback;
916 int rv = socket.Connect(connect_callback.callback());
917 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
918
919 // Advance to t=3.1s
920 // Should still be pending, as this is before the minimum timeout.
921 task_environment_.FastForwardBy(base::Milliseconds(3100));
922 EXPECT_FALSE(connect_callback.have_result());
923 EXPECT_FALSE(socket.IsConnected());
924
925 // Advance to t=4.1s
926 // Should still be pending. This is after the minimum timeout, but before the
927 // maximum.
928 task_environment_.FastForwardBy(base::Seconds(1));
929 EXPECT_FALSE(connect_callback.have_result());
930 EXPECT_FALSE(socket.IsConnected());
931
932 // Advance to t=10.1s
933 // Should now be timed out, as this is after the maximum timeout.
934 task_environment_.FastForwardBy(base::Seconds(6));
935 rv = connect_callback.GetResult(rv);
936 ASSERT_THAT(rv, IsError(ERR_TIMED_OUT));
937
938 // 1 attempt was made.
939 EXPECT_EQ(1, socket.connect_internal_counter());
940 }
941
942 // Tests that the minimum timeout is used when the adaptive timeout using RTT
943 // ends up being too low.
TEST_F(TCPClientSocketMockTimeTest,ConnectAttemptTimeoutUsesMinWhenRTTLow)944 TEST_F(TCPClientSocketMockTimeTest, ConnectAttemptTimeoutUsesMinWhenRTTLow) {
945 OverrideTcpConnectAttemptTimeout override_timeout(5, base::Seconds(4),
946 base::Seconds(10));
947
948 // Set the estimated RTT to 1 millisecond.
949 TestNetworkQualityEstimator network_quality_estimator;
950 network_quality_estimator.SetStartTimeNullTransportRtt(base::Milliseconds(1));
951
952 IPEndPoint server_address(IPAddress::IPv4Localhost(), 80);
953
954 NeverConnectingTCPClientSocket socket(AddressList(server_address), nullptr,
955 &network_quality_estimator, nullptr,
956 NetLogSource());
957
958 // Start connecting.
959 TestCompletionCallback connect_callback;
960 int rv = socket.Connect(connect_callback.callback());
961 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
962
963 // Advance to t=1.1s
964 // Should be pending, since although the adaptive timeout has been reached, it
965 // is lower than the minimum timeout.
966 task_environment_.FastForwardBy(base::Milliseconds(1100));
967 EXPECT_FALSE(connect_callback.have_result());
968 EXPECT_FALSE(socket.IsConnected());
969
970 // Advance to t=4.1s
971 // Should have timed out due to hitting the minimum timeout.
972 task_environment_.FastForwardBy(base::Seconds(3));
973 rv = connect_callback.GetResult(rv);
974 ASSERT_THAT(rv, IsError(ERR_TIMED_OUT));
975
976 // 1 attempt was made.
977 EXPECT_EQ(1, socket.connect_internal_counter());
978 }
979
980 // Tests that the maximum timeout is used when the adaptive timeout from RTT is
981 // too high.
TEST_F(TCPClientSocketMockTimeTest,ConnectAttemptTimeoutUsesMinWhenRTTHigh)982 TEST_F(TCPClientSocketMockTimeTest, ConnectAttemptTimeoutUsesMinWhenRTTHigh) {
983 OverrideTcpConnectAttemptTimeout override_timeout(5, base::Seconds(4),
984 base::Seconds(10));
985
986 // Set the estimated RTT to 5 seconds.
987 TestNetworkQualityEstimator network_quality_estimator;
988 network_quality_estimator.SetStartTimeNullTransportRtt(base::Seconds(5));
989
990 IPEndPoint server_address(IPAddress::IPv4Localhost(), 80);
991
992 NeverConnectingTCPClientSocket socket(AddressList(server_address), nullptr,
993 &network_quality_estimator, nullptr,
994 NetLogSource());
995
996 // Start connecting.
997 TestCompletionCallback connect_callback;
998 int rv = socket.Connect(connect_callback.callback());
999 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
1000
1001 // Advance to t=10.1s
1002 // The socket should have timed out due to hitting the maximum timeout. Had
1003 // the adaptive timeout been used, the socket would instead be timing out at
1004 // t=25s.
1005 task_environment_.FastForwardBy(base::Milliseconds(10100));
1006 rv = connect_callback.GetResult(rv);
1007 ASSERT_THAT(rv, IsError(ERR_TIMED_OUT));
1008
1009 // 1 attempt was made.
1010 EXPECT_EQ(1, socket.connect_internal_counter());
1011 }
1012
1013 // Tests that an adaptive timeout is used for TCP connection attempts based on
1014 // the estimated RTT.
TEST_F(TCPClientSocketMockTimeTest,ConnectAttemptTimeoutUsesRTT)1015 TEST_F(TCPClientSocketMockTimeTest, ConnectAttemptTimeoutUsesRTT) {
1016 OverrideTcpConnectAttemptTimeout override_timeout(5, base::Seconds(4),
1017 base::Seconds(10));
1018
1019 // Set the estimated RTT to 1 second. Since the multiplier is set to 5, the
1020 // total adaptive timeout will be 5 seconds.
1021 TestNetworkQualityEstimator network_quality_estimator;
1022 network_quality_estimator.SetStartTimeNullTransportRtt(base::Seconds(1));
1023
1024 IPEndPoint server_address(IPAddress::IPv4Localhost(), 80);
1025
1026 NeverConnectingTCPClientSocket socket(AddressList(server_address), nullptr,
1027 &network_quality_estimator, nullptr,
1028 NetLogSource());
1029
1030 // Start connecting.
1031 TestCompletionCallback connect_callback;
1032 int rv = socket.Connect(connect_callback.callback());
1033 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
1034
1035 // Advance to t=4.1s
1036 // The socket should still be pending. Had the minimum timeout been enforced,
1037 // it would instead have timed out now.
1038 task_environment_.FastForwardBy(base::Milliseconds(4100));
1039 EXPECT_FALSE(connect_callback.have_result());
1040 EXPECT_FALSE(socket.IsConnected());
1041
1042 // Advance to t=5.1s
1043 // The adaptive timeout was at t=5s, so it should now be timed out.
1044 task_environment_.FastForwardBy(base::Seconds(1));
1045 rv = connect_callback.GetResult(rv);
1046 ASSERT_THAT(rv, IsError(ERR_TIMED_OUT));
1047
1048 // 1 attempt was made.
1049 EXPECT_EQ(1, socket.connect_internal_counter());
1050 }
1051
1052 // Tests that when multiple TCP connect attempts are made, the timeout for each
1053 // one is applied independently.
TEST_F(TCPClientSocketMockTimeTest,ConnectAttemptTimeoutIndependent)1054 TEST_F(TCPClientSocketMockTimeTest, ConnectAttemptTimeoutIndependent) {
1055 OverrideTcpConnectAttemptTimeout override_timeout(5, base::Seconds(4),
1056 base::Seconds(10));
1057
1058 // This test will attempt connecting to 5 endpoints.
1059 const size_t kNumIps = 5;
1060
1061 AddressList addresses;
1062 for (size_t i = 0; i < kNumIps; ++i)
1063 addresses.push_back(IPEndPoint(IPAddress::IPv4Localhost(), 80 + i));
1064
1065 NeverConnectingTCPClientSocket socket(addresses, nullptr, nullptr, nullptr,
1066 NetLogSource());
1067
1068 // Start connecting.
1069 TestCompletionCallback connect_callback;
1070 int rv = socket.Connect(connect_callback.callback());
1071 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
1072
1073 // Advance to t=49s
1074 // Should still be pending.
1075 task_environment_.FastForwardBy(base::Seconds(49));
1076 EXPECT_FALSE(connect_callback.have_result());
1077 EXPECT_FALSE(socket.IsConnected());
1078
1079 // Advance to t=50.1s
1080 // All attempts should take 50 seconds to complete (5 attempts, 10 seconds
1081 // each). So by this point the overall connect attempt will have timed out.
1082 task_environment_.FastForwardBy(base::Milliseconds(1100));
1083 rv = connect_callback.GetResult(rv);
1084 ASSERT_THAT(rv, IsError(ERR_TIMED_OUT));
1085
1086 // 5 attempts were made.
1087 EXPECT_EQ(5, socket.connect_internal_counter());
1088 }
1089
1090 } // namespace
1091
1092 } // namespace net
1093