1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/socket/transport_client_socket_pool_test_util.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/load_timing_info.h"
17 #include "net/base/load_timing_info_test_util.h"
18 #include "net/base/net_util.h"
19 #include "net/socket/client_socket_handle.h"
20 #include "net/socket/ssl_client_socket.h"
21 #include "net/udp/datagram_client_socket.h"
22 #include "testing/gtest/include/gtest/gtest.h"
28 IPAddressNumber
ParseIP(const std::string
& ip
) {
29 IPAddressNumber number
;
30 CHECK(ParseIPLiteralToNumber(ip
, &number
));
34 // A StreamSocket which connects synchronously and successfully.
35 class MockConnectClientSocket
: public StreamSocket
{
37 MockConnectClientSocket(const AddressList
& addrlist
, net::NetLog
* net_log
)
40 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_SOCKET
)),
41 use_tcp_fastopen_(false) {}
43 // StreamSocket implementation.
44 int Connect(const CompletionCallback
& callback
) override
{
48 void Disconnect() override
{ connected_
= false; }
49 bool IsConnected() const override
{ return connected_
; }
50 bool IsConnectedAndIdle() const override
{ return connected_
; }
52 int GetPeerAddress(IPEndPoint
* address
) const override
{
53 *address
= addrlist_
.front();
56 int GetLocalAddress(IPEndPoint
* address
) const override
{
58 return ERR_SOCKET_NOT_CONNECTED
;
59 if (addrlist_
.front().GetFamily() == ADDRESS_FAMILY_IPV4
)
60 SetIPv4Address(address
);
62 SetIPv6Address(address
);
65 const BoundNetLog
& NetLog() const override
{ return net_log_
; }
67 void SetSubresourceSpeculation() override
{}
68 void SetOmniboxSpeculation() override
{}
69 bool WasEverUsed() const override
{ return false; }
70 void EnableTCPFastOpenIfSupported() override
{ use_tcp_fastopen_
= true; }
71 bool UsingTCPFastOpen() const override
{ return use_tcp_fastopen_
; }
72 bool WasNpnNegotiated() const override
{ return false; }
73 NextProto
GetNegotiatedProtocol() const override
{ return kProtoUnknown
; }
74 bool GetSSLInfo(SSLInfo
* ssl_info
) override
{ return false; }
75 void GetConnectionAttempts(ConnectionAttempts
* out
) const override
{
78 void ClearConnectionAttempts() override
{}
79 void AddConnectionAttempts(const ConnectionAttempts
& attempts
) override
{}
81 // Socket implementation.
82 int Read(IOBuffer
* buf
,
84 const CompletionCallback
& callback
) override
{
87 int Write(IOBuffer
* buf
,
89 const CompletionCallback
& callback
) override
{
92 int SetReceiveBufferSize(int32 size
) override
{ return OK
; }
93 int SetSendBufferSize(int32 size
) override
{ return OK
; }
97 const AddressList addrlist_
;
99 bool use_tcp_fastopen_
;
101 DISALLOW_COPY_AND_ASSIGN(MockConnectClientSocket
);
104 class MockFailingClientSocket
: public StreamSocket
{
106 MockFailingClientSocket(const AddressList
& addrlist
, net::NetLog
* net_log
)
107 : addrlist_(addrlist
),
108 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_SOCKET
)),
109 use_tcp_fastopen_(false) {}
111 // StreamSocket implementation.
112 int Connect(const CompletionCallback
& callback
) override
{
113 return ERR_CONNECTION_FAILED
;
116 void Disconnect() override
{}
118 bool IsConnected() const override
{ return false; }
119 bool IsConnectedAndIdle() const override
{ return false; }
120 int GetPeerAddress(IPEndPoint
* address
) const override
{
121 return ERR_UNEXPECTED
;
123 int GetLocalAddress(IPEndPoint
* address
) const override
{
124 return ERR_UNEXPECTED
;
126 const BoundNetLog
& NetLog() const override
{ return net_log_
; }
128 void SetSubresourceSpeculation() override
{}
129 void SetOmniboxSpeculation() override
{}
130 bool WasEverUsed() const override
{ return false; }
131 void EnableTCPFastOpenIfSupported() override
{ use_tcp_fastopen_
= true; }
132 bool UsingTCPFastOpen() const override
{ return use_tcp_fastopen_
; }
133 bool WasNpnNegotiated() const override
{ return false; }
134 NextProto
GetNegotiatedProtocol() const override
{ return kProtoUnknown
; }
135 bool GetSSLInfo(SSLInfo
* ssl_info
) override
{ return false; }
136 void GetConnectionAttempts(ConnectionAttempts
* out
) const override
{
138 for (const auto& addr
: addrlist_
)
139 out
->push_back(ConnectionAttempt(addr
, ERR_CONNECTION_FAILED
));
141 void ClearConnectionAttempts() override
{}
142 void AddConnectionAttempts(const ConnectionAttempts
& attempts
) override
{}
144 // Socket implementation.
145 int Read(IOBuffer
* buf
,
147 const CompletionCallback
& callback
) override
{
151 int Write(IOBuffer
* buf
,
153 const CompletionCallback
& callback
) override
{
156 int SetReceiveBufferSize(int32 size
) override
{ return OK
; }
157 int SetSendBufferSize(int32 size
) override
{ return OK
; }
160 const AddressList addrlist_
;
161 BoundNetLog net_log_
;
162 bool use_tcp_fastopen_
;
164 DISALLOW_COPY_AND_ASSIGN(MockFailingClientSocket
);
167 class MockTriggerableClientSocket
: public StreamSocket
{
169 // |should_connect| indicates whether the socket should successfully complete
171 MockTriggerableClientSocket(const AddressList
& addrlist
,
173 net::NetLog
* net_log
)
174 : should_connect_(should_connect
),
175 is_connected_(false),
177 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_SOCKET
)),
178 use_tcp_fastopen_(false),
179 weak_factory_(this) {}
181 // Call this method to get a closure which will trigger the connect callback
182 // when called. The closure can be called even after the socket is deleted; it
183 // will safely do nothing.
184 base::Closure
GetConnectCallback() {
185 return base::Bind(&MockTriggerableClientSocket::DoCallback
,
186 weak_factory_
.GetWeakPtr());
189 static scoped_ptr
<StreamSocket
> MakeMockPendingClientSocket(
190 const AddressList
& addrlist
,
192 net::NetLog
* net_log
) {
193 scoped_ptr
<MockTriggerableClientSocket
> socket(
194 new MockTriggerableClientSocket(addrlist
, should_connect
, net_log
));
195 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
196 socket
->GetConnectCallback());
197 return socket
.Pass();
200 static scoped_ptr
<StreamSocket
> MakeMockDelayedClientSocket(
201 const AddressList
& addrlist
,
203 const base::TimeDelta
& delay
,
204 net::NetLog
* net_log
) {
205 scoped_ptr
<MockTriggerableClientSocket
> socket(
206 new MockTriggerableClientSocket(addrlist
, should_connect
, net_log
));
207 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
208 FROM_HERE
, socket
->GetConnectCallback(), delay
);
209 return socket
.Pass();
212 static scoped_ptr
<StreamSocket
> MakeMockStalledClientSocket(
213 const AddressList
& addrlist
,
214 net::NetLog
* net_log
,
216 scoped_ptr
<MockTriggerableClientSocket
> socket(
217 new MockTriggerableClientSocket(addrlist
, true, net_log
));
219 DCHECK_LE(1u, addrlist
.size());
220 ConnectionAttempts attempts
;
221 attempts
.push_back(ConnectionAttempt(addrlist
[0], ERR_CONNECTION_FAILED
));
222 socket
->AddConnectionAttempts(attempts
);
224 return socket
.Pass();
227 // StreamSocket implementation.
228 int Connect(const CompletionCallback
& callback
) override
{
229 DCHECK(callback_
.is_null());
230 callback_
= callback
;
231 return ERR_IO_PENDING
;
234 void Disconnect() override
{}
236 bool IsConnected() const override
{ return is_connected_
; }
237 bool IsConnectedAndIdle() const override
{ return is_connected_
; }
238 int GetPeerAddress(IPEndPoint
* address
) const override
{
239 *address
= addrlist_
.front();
242 int GetLocalAddress(IPEndPoint
* address
) const override
{
244 return ERR_SOCKET_NOT_CONNECTED
;
245 if (addrlist_
.front().GetFamily() == ADDRESS_FAMILY_IPV4
)
246 SetIPv4Address(address
);
248 SetIPv6Address(address
);
251 const BoundNetLog
& NetLog() const override
{ return net_log_
; }
253 void SetSubresourceSpeculation() override
{}
254 void SetOmniboxSpeculation() override
{}
255 bool WasEverUsed() const override
{ return false; }
256 void EnableTCPFastOpenIfSupported() override
{ use_tcp_fastopen_
= true; }
257 bool UsingTCPFastOpen() const override
{ return use_tcp_fastopen_
; }
258 bool WasNpnNegotiated() const override
{ return false; }
259 NextProto
GetNegotiatedProtocol() const override
{ return kProtoUnknown
; }
260 bool GetSSLInfo(SSLInfo
* ssl_info
) override
{ return false; }
261 void GetConnectionAttempts(ConnectionAttempts
* out
) const override
{
262 *out
= connection_attempts_
;
264 void ClearConnectionAttempts() override
{ connection_attempts_
.clear(); }
265 void AddConnectionAttempts(const ConnectionAttempts
& attempts
) override
{
266 connection_attempts_
.insert(connection_attempts_
.begin(), attempts
.begin(),
270 // Socket implementation.
271 int Read(IOBuffer
* buf
,
273 const CompletionCallback
& callback
) override
{
277 int Write(IOBuffer
* buf
,
279 const CompletionCallback
& callback
) override
{
282 int SetReceiveBufferSize(int32 size
) override
{ return OK
; }
283 int SetSendBufferSize(int32 size
) override
{ return OK
; }
287 is_connected_
= should_connect_
;
288 callback_
.Run(is_connected_
? OK
: ERR_CONNECTION_FAILED
);
291 bool should_connect_
;
293 const AddressList addrlist_
;
294 BoundNetLog net_log_
;
295 CompletionCallback callback_
;
296 bool use_tcp_fastopen_
;
297 ConnectionAttempts connection_attempts_
;
299 base::WeakPtrFactory
<MockTriggerableClientSocket
> weak_factory_
;
301 DISALLOW_COPY_AND_ASSIGN(MockTriggerableClientSocket
);
306 void TestLoadTimingInfoConnectedReused(const ClientSocketHandle
& handle
) {
307 LoadTimingInfo load_timing_info
;
308 // Only pass true in as |is_reused|, as in general, HttpStream types should
309 // have stricter concepts of reuse than socket pools.
310 EXPECT_TRUE(handle
.GetLoadTimingInfo(true, &load_timing_info
));
312 EXPECT_TRUE(load_timing_info
.socket_reused
);
313 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
315 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
316 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info
);
319 void TestLoadTimingInfoConnectedNotReused(const ClientSocketHandle
& handle
) {
320 EXPECT_FALSE(handle
.is_reused());
322 LoadTimingInfo load_timing_info
;
323 EXPECT_TRUE(handle
.GetLoadTimingInfo(false, &load_timing_info
));
325 EXPECT_FALSE(load_timing_info
.socket_reused
);
326 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
328 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
329 CONNECT_TIMING_HAS_DNS_TIMES
);
330 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info
);
332 TestLoadTimingInfoConnectedReused(handle
);
335 void SetIPv4Address(IPEndPoint
* address
) {
336 *address
= IPEndPoint(ParseIP("1.1.1.1"), 80);
339 void SetIPv6Address(IPEndPoint
* address
) {
340 *address
= IPEndPoint(ParseIP("1:abcd::3:4:ff"), 80);
343 MockTransportClientSocketFactory::MockTransportClientSocketFactory(
346 allocation_count_(0),
347 client_socket_type_(MOCK_CLIENT_SOCKET
),
348 client_socket_types_(NULL
),
349 client_socket_index_(0),
350 client_socket_index_max_(0),
351 delay_(base::TimeDelta::FromMilliseconds(
352 ClientSocketPool::kMaxConnectRetryIntervalMs
)) {}
354 MockTransportClientSocketFactory::~MockTransportClientSocketFactory() {}
356 scoped_ptr
<DatagramClientSocket
>
357 MockTransportClientSocketFactory::CreateDatagramClientSocket(
358 DatagramSocket::BindType bind_type
,
359 const RandIntCallback
& rand_int_cb
,
361 const NetLog::Source
& source
) {
363 return scoped_ptr
<DatagramClientSocket
>();
366 scoped_ptr
<StreamSocket
>
367 MockTransportClientSocketFactory::CreateTransportClientSocket(
368 const AddressList
& addresses
,
369 NetLog
* /* net_log */,
370 const NetLog::Source
& /* source */) {
373 ClientSocketType type
= client_socket_type_
;
374 if (client_socket_types_
&& client_socket_index_
< client_socket_index_max_
) {
375 type
= client_socket_types_
[client_socket_index_
++];
379 case MOCK_CLIENT_SOCKET
:
380 return scoped_ptr
<StreamSocket
>(
381 new MockConnectClientSocket(addresses
, net_log_
));
382 case MOCK_FAILING_CLIENT_SOCKET
:
383 return scoped_ptr
<StreamSocket
>(
384 new MockFailingClientSocket(addresses
, net_log_
));
385 case MOCK_PENDING_CLIENT_SOCKET
:
386 return MockTriggerableClientSocket::MakeMockPendingClientSocket(
387 addresses
, true, net_log_
);
388 case MOCK_PENDING_FAILING_CLIENT_SOCKET
:
389 return MockTriggerableClientSocket::MakeMockPendingClientSocket(
390 addresses
, false, net_log_
);
391 case MOCK_DELAYED_CLIENT_SOCKET
:
392 return MockTriggerableClientSocket::MakeMockDelayedClientSocket(
393 addresses
, true, delay_
, net_log_
);
394 case MOCK_DELAYED_FAILING_CLIENT_SOCKET
:
395 return MockTriggerableClientSocket::MakeMockDelayedClientSocket(
396 addresses
, false, delay_
, net_log_
);
397 case MOCK_STALLED_CLIENT_SOCKET
:
398 return MockTriggerableClientSocket::MakeMockStalledClientSocket(
399 addresses
, net_log_
, false);
400 case MOCK_STALLED_FAILING_CLIENT_SOCKET
:
401 return MockTriggerableClientSocket::MakeMockStalledClientSocket(
402 addresses
, net_log_
, true);
403 case MOCK_TRIGGERABLE_CLIENT_SOCKET
: {
404 scoped_ptr
<MockTriggerableClientSocket
> rv(
405 new MockTriggerableClientSocket(addresses
, true, net_log_
));
406 triggerable_sockets_
.push(rv
->GetConnectCallback());
407 // run_loop_quit_closure_ behaves like a condition variable. It will
408 // wake up WaitForTriggerableSocketCreation() if it is sleeping. We
409 // don't need to worry about atomicity because this code is
411 if (!run_loop_quit_closure_
.is_null())
412 run_loop_quit_closure_
.Run();
417 return scoped_ptr
<StreamSocket
>(
418 new MockConnectClientSocket(addresses
, net_log_
));
422 scoped_ptr
<SSLClientSocket
>
423 MockTransportClientSocketFactory::CreateSSLClientSocket(
424 scoped_ptr
<ClientSocketHandle
> transport_socket
,
425 const HostPortPair
& host_and_port
,
426 const SSLConfig
& ssl_config
,
427 const SSLClientSocketContext
& context
) {
429 return scoped_ptr
<SSLClientSocket
>();
432 void MockTransportClientSocketFactory::ClearSSLSessionCache() {
436 void MockTransportClientSocketFactory::set_client_socket_types(
437 ClientSocketType
* type_list
,
439 DCHECK_GT(num_types
, 0);
440 client_socket_types_
= type_list
;
441 client_socket_index_
= 0;
442 client_socket_index_max_
= num_types
;
446 MockTransportClientSocketFactory::WaitForTriggerableSocketCreation() {
447 while (triggerable_sockets_
.empty()) {
448 base::RunLoop run_loop
;
449 run_loop_quit_closure_
= run_loop
.QuitClosure();
451 run_loop_quit_closure_
.Reset();
453 base::Closure trigger
= triggerable_sockets_
.front();
454 triggerable_sockets_
.pop();