OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "net/socket/websocket_transport_client_socket_pool.h" | |
6 | |
7 #include <queue> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/bind_helpers.h" | |
11 #include "base/callback.h" | |
12 #include "base/compiler_specific.h" | |
13 #include "base/logging.h" | |
14 #include "base/macros.h" | |
15 #include "base/message_loop/message_loop.h" | |
16 #include "base/run_loop.h" | |
17 #include "base/threading/platform_thread.h" | |
18 #include "net/base/capturing_net_log.h" | |
19 #include "net/base/ip_endpoint.h" | |
20 #include "net/base/load_timing_info.h" | |
21 #include "net/base/load_timing_info_test_util.h" | |
22 #include "net/base/net_errors.h" | |
23 #include "net/base/net_util.h" | |
24 #include "net/base/test_completion_callback.h" | |
25 #include "net/dns/mock_host_resolver.h" | |
26 #include "net/socket/client_socket_factory.h" | |
27 #include "net/socket/client_socket_handle.h" | |
28 #include "net/socket/client_socket_pool_histograms.h" | |
29 #include "net/socket/socket_test_util.h" | |
30 #include "net/socket/ssl_client_socket.h" | |
31 #include "net/socket/stream_socket.h" | |
32 #include "testing/gtest/include/gtest/gtest.h" | |
33 | |
34 namespace net { | |
35 | |
36 using internal::ClientSocketPoolBaseHelper; | |
37 | |
38 namespace { | |
39 | |
40 const int kMaxSockets = 32; | |
41 const int kMaxSocketsPerGroup = 6; | |
42 const net::RequestPriority kDefaultPriority = LOW; | |
43 | |
44 // Make sure |handle| sets load times correctly when it has been assigned a | |
45 // reused socket. | |
46 void TestLoadTimingInfoConnectedReused(const ClientSocketHandle& handle) { | |
47 LoadTimingInfo load_timing_info; | |
48 // Only pass true in as |is_reused|, as in general, HttpStream types should | |
49 // have stricter concepts of reuse than socket pools. | |
50 EXPECT_TRUE(handle.GetLoadTimingInfo(true, &load_timing_info)); | |
51 | |
52 EXPECT_TRUE(load_timing_info.socket_reused); | |
53 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
54 | |
55 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); | |
56 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
57 } | |
58 | |
59 // Make sure |handle| sets load times correctly when it has been assigned a | |
60 // fresh socket. Also runs TestLoadTimingInfoConnectedReused, since the owner | |
61 // of a connection where |is_reused| is false may consider the connection | |
62 // reused. | |
63 void TestLoadTimingInfoConnectedNotReused(const ClientSocketHandle& handle) { | |
64 EXPECT_FALSE(handle.is_reused()); | |
65 | |
66 LoadTimingInfo load_timing_info; | |
67 EXPECT_TRUE(handle.GetLoadTimingInfo(false, &load_timing_info)); | |
68 | |
69 EXPECT_FALSE(load_timing_info.socket_reused); | |
70 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
71 | |
72 ExpectConnectTimingHasTimes(load_timing_info.connect_timing, | |
73 CONNECT_TIMING_HAS_DNS_TIMES); | |
74 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
75 | |
76 TestLoadTimingInfoConnectedReused(handle); | |
77 } | |
78 | |
79 void SetIPv4Address(IPEndPoint* address) { | |
80 IPAddressNumber number; | |
81 CHECK(ParseIPLiteralToNumber("1.1.1.1", &number)); | |
82 *address = IPEndPoint(number, 80); | |
83 } | |
84 | |
85 void SetIPv6Address(IPEndPoint* address) { | |
86 IPAddressNumber number; | |
87 CHECK(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number)); | |
88 *address = IPEndPoint(number, 80); | |
89 } | |
90 | |
91 class MockClientSocket : public StreamSocket { | |
Johnny
2014/06/16 23:41:11
Do these mocks deviate significantly from transpor
Adam Rice
2014/06/19 13:55:21
MockClientSocket has gained an implementation of G
| |
92 public: | |
93 MockClientSocket(const AddressList& addrlist, net::NetLog* net_log) | |
94 : connected_(false), | |
95 addrlist_(addrlist), | |
96 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {} | |
97 | |
98 // StreamSocket implementation. | |
99 virtual int Connect(const CompletionCallback& callback) OVERRIDE { | |
100 connected_ = true; | |
101 return OK; | |
102 } | |
103 virtual void Disconnect() OVERRIDE { connected_ = false; } | |
104 virtual bool IsConnected() const OVERRIDE { return connected_; } | |
105 virtual bool IsConnectedAndIdle() const OVERRIDE { return connected_; } | |
106 virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE { | |
107 *address = addrlist_.front(); | |
108 return OK; | |
109 } | |
110 virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE { | |
111 if (!connected_) | |
112 return ERR_SOCKET_NOT_CONNECTED; | |
113 if (addrlist_.front().GetFamily() == ADDRESS_FAMILY_IPV4) | |
114 SetIPv4Address(address); | |
115 else | |
116 SetIPv6Address(address); | |
117 return OK; | |
118 } | |
119 virtual const BoundNetLog& NetLog() const OVERRIDE { return net_log_; } | |
120 | |
121 virtual void SetSubresourceSpeculation() OVERRIDE {} | |
122 virtual void SetOmniboxSpeculation() OVERRIDE {} | |
123 virtual bool WasEverUsed() const OVERRIDE { return false; } | |
124 virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } | |
125 virtual bool WasNpnNegotiated() const OVERRIDE { return false; } | |
126 virtual NextProto GetNegotiatedProtocol() const OVERRIDE { | |
127 return kProtoUnknown; | |
128 } | |
129 virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { return false; } | |
130 | |
131 // Socket implementation. | |
132 virtual int Read(IOBuffer* buf, | |
133 int buf_len, | |
134 const CompletionCallback& callback) OVERRIDE { | |
135 return ERR_FAILED; | |
136 } | |
137 virtual int Write(IOBuffer* buf, | |
138 int buf_len, | |
139 const CompletionCallback& callback) OVERRIDE { | |
140 return ERR_FAILED; | |
141 } | |
142 virtual int SetReceiveBufferSize(int32 size) OVERRIDE { return OK; } | |
143 virtual int SetSendBufferSize(int32 size) OVERRIDE { return OK; } | |
144 | |
145 private: | |
146 bool connected_; | |
147 const AddressList addrlist_; | |
148 BoundNetLog net_log_; | |
149 | |
150 DISALLOW_COPY_AND_ASSIGN(MockClientSocket); | |
151 }; | |
152 | |
153 class MockFailingClientSocket : public StreamSocket { | |
154 public: | |
155 MockFailingClientSocket(const AddressList& addrlist, net::NetLog* net_log) | |
156 : addrlist_(addrlist), | |
157 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {} | |
158 | |
159 // StreamSocket implementation. | |
160 virtual int Connect(const CompletionCallback& callback) OVERRIDE { | |
161 return ERR_CONNECTION_FAILED; | |
162 } | |
163 | |
164 virtual void Disconnect() OVERRIDE {} | |
165 | |
166 virtual bool IsConnected() const OVERRIDE { return false; } | |
167 virtual bool IsConnectedAndIdle() const OVERRIDE { return false; } | |
168 virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE { | |
169 return ERR_UNEXPECTED; | |
170 } | |
171 virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE { | |
172 return ERR_UNEXPECTED; | |
173 } | |
174 virtual const BoundNetLog& NetLog() const OVERRIDE { return net_log_; } | |
175 | |
176 virtual void SetSubresourceSpeculation() OVERRIDE {} | |
177 virtual void SetOmniboxSpeculation() OVERRIDE {} | |
178 virtual bool WasEverUsed() const OVERRIDE { return false; } | |
179 virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } | |
180 virtual bool WasNpnNegotiated() const OVERRIDE { return false; } | |
181 virtual NextProto GetNegotiatedProtocol() const OVERRIDE { | |
182 return kProtoUnknown; | |
183 } | |
184 virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { return false; } | |
185 | |
186 // Socket implementation. | |
187 virtual int Read(IOBuffer* buf, | |
188 int buf_len, | |
189 const CompletionCallback& callback) OVERRIDE { | |
190 return ERR_FAILED; | |
191 } | |
192 | |
193 virtual int Write(IOBuffer* buf, | |
194 int buf_len, | |
195 const CompletionCallback& callback) OVERRIDE { | |
196 return ERR_FAILED; | |
197 } | |
198 virtual int SetReceiveBufferSize(int32 size) OVERRIDE { return OK; } | |
199 virtual int SetSendBufferSize(int32 size) OVERRIDE { return OK; } | |
200 | |
201 private: | |
202 const AddressList addrlist_; | |
203 BoundNetLog net_log_; | |
204 | |
205 DISALLOW_COPY_AND_ASSIGN(MockFailingClientSocket); | |
206 }; | |
207 | |
208 class MockTriggerableClientSocket : public StreamSocket { | |
209 public: | |
210 // |should_connect| indicates whether the socket should successfully complete | |
211 // or fail. | |
212 MockTriggerableClientSocket(const AddressList& addrlist, | |
213 bool should_connect, | |
214 net::NetLog* net_log) | |
215 : should_connect_(should_connect), | |
216 is_connected_(false), | |
217 addrlist_(addrlist), | |
218 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), | |
219 weak_factory_(this) {} | |
220 | |
221 // Call this method to get a closure which will trigger the connect callback | |
222 // when called. The closure can be called even after the socket is deleted; it | |
223 // will safely do nothing. | |
224 base::Closure GetConnectCallback() { | |
225 return base::Bind(&MockTriggerableClientSocket::DoCallback, | |
226 weak_factory_.GetWeakPtr()); | |
227 } | |
228 | |
229 static scoped_ptr<StreamSocket> MakeMockPendingClientSocket( | |
230 const AddressList& addrlist, | |
231 bool should_connect, | |
232 net::NetLog* net_log) { | |
233 scoped_ptr<MockTriggerableClientSocket> socket( | |
234 new MockTriggerableClientSocket(addrlist, should_connect, net_log)); | |
235 base::MessageLoop::current()->PostTask(FROM_HERE, | |
236 socket->GetConnectCallback()); | |
237 return socket.PassAs<StreamSocket>(); | |
238 } | |
239 | |
240 static scoped_ptr<StreamSocket> MakeMockDelayedClientSocket( | |
241 const AddressList& addrlist, | |
242 bool should_connect, | |
243 const base::TimeDelta& delay, | |
244 net::NetLog* net_log) { | |
245 scoped_ptr<MockTriggerableClientSocket> socket( | |
246 new MockTriggerableClientSocket(addrlist, should_connect, net_log)); | |
247 base::MessageLoop::current()->PostDelayedTask( | |
248 FROM_HERE, socket->GetConnectCallback(), delay); | |
249 return socket.PassAs<StreamSocket>(); | |
250 } | |
251 | |
252 static scoped_ptr<StreamSocket> MakeMockStalledClientSocket( | |
253 const AddressList& addrlist, | |
254 net::NetLog* net_log) { | |
255 scoped_ptr<MockTriggerableClientSocket> socket( | |
256 new MockTriggerableClientSocket(addrlist, true, net_log)); | |
257 return socket.PassAs<StreamSocket>(); | |
258 } | |
259 | |
260 // StreamSocket implementation. | |
261 virtual int Connect(const CompletionCallback& callback) OVERRIDE { | |
262 DCHECK(callback_.is_null()); | |
263 callback_ = callback; | |
264 return ERR_IO_PENDING; | |
265 } | |
266 | |
267 virtual void Disconnect() OVERRIDE {} | |
268 | |
269 virtual bool IsConnected() const OVERRIDE { return is_connected_; } | |
270 virtual bool IsConnectedAndIdle() const OVERRIDE { return is_connected_; } | |
271 virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE { | |
272 *address = addrlist_.front(); | |
273 return OK; | |
274 } | |
275 virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE { | |
276 if (!is_connected_) | |
277 return ERR_SOCKET_NOT_CONNECTED; | |
278 if (addrlist_.front().GetFamily() == ADDRESS_FAMILY_IPV4) | |
279 SetIPv4Address(address); | |
280 else | |
281 SetIPv6Address(address); | |
282 return OK; | |
283 } | |
284 virtual const BoundNetLog& NetLog() const OVERRIDE { return net_log_; } | |
285 | |
286 virtual void SetSubresourceSpeculation() OVERRIDE {} | |
287 virtual void SetOmniboxSpeculation() OVERRIDE {} | |
288 virtual bool WasEverUsed() const OVERRIDE { return false; } | |
289 virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } | |
290 virtual bool WasNpnNegotiated() const OVERRIDE { return false; } | |
291 virtual NextProto GetNegotiatedProtocol() const OVERRIDE { | |
292 return kProtoUnknown; | |
293 } | |
294 virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { return false; } | |
295 | |
296 // Socket implementation. | |
297 virtual int Read(IOBuffer* buf, | |
298 int buf_len, | |
299 const CompletionCallback& callback) OVERRIDE { | |
300 return ERR_FAILED; | |
301 } | |
302 | |
303 virtual int Write(IOBuffer* buf, | |
304 int buf_len, | |
305 const CompletionCallback& callback) OVERRIDE { | |
306 return ERR_FAILED; | |
307 } | |
308 virtual int SetReceiveBufferSize(int32 size) OVERRIDE { return OK; } | |
309 virtual int SetSendBufferSize(int32 size) OVERRIDE { return OK; } | |
310 | |
311 private: | |
312 void DoCallback() { | |
313 is_connected_ = should_connect_; | |
314 callback_.Run(is_connected_ ? OK : ERR_CONNECTION_FAILED); | |
315 } | |
316 | |
317 bool should_connect_; | |
318 bool is_connected_; | |
319 const AddressList addrlist_; | |
320 BoundNetLog net_log_; | |
321 CompletionCallback callback_; | |
322 | |
323 base::WeakPtrFactory<MockTriggerableClientSocket> weak_factory_; | |
324 | |
325 DISALLOW_COPY_AND_ASSIGN(MockTriggerableClientSocket); | |
326 }; | |
327 | |
328 class MockClientSocketFactory : public ClientSocketFactory { | |
329 public: | |
330 enum ClientSocketType { | |
331 MOCK_CLIENT_SOCKET, | |
332 MOCK_FAILING_CLIENT_SOCKET, | |
333 MOCK_PENDING_CLIENT_SOCKET, | |
334 MOCK_PENDING_FAILING_CLIENT_SOCKET, | |
335 // A delayed socket will pause before connecting through the message loop. | |
336 MOCK_DELAYED_CLIENT_SOCKET, | |
337 // A delayed socket that fails. | |
338 MOCK_DELAYED_FAILING_CLIENT_SOCKET, | |
339 // A stalled socket that never connects at all. | |
340 MOCK_STALLED_CLIENT_SOCKET, | |
341 // A socket that can be triggered to connect explicitly. | |
342 MOCK_TRIGGERABLE_CLIENT_SOCKET, | |
343 }; | |
344 | |
345 explicit MockClientSocketFactory(NetLog* net_log) | |
346 : net_log_(net_log), | |
347 allocation_count_(0), | |
348 client_socket_type_(MOCK_CLIENT_SOCKET), | |
349 client_socket_types_(NULL), | |
350 client_socket_index_(0), | |
351 client_socket_index_max_(0), | |
352 delay_(base::TimeDelta::FromMilliseconds( | |
353 ClientSocketPool::kMaxConnectRetryIntervalMs)) {} | |
354 | |
355 virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket( | |
356 DatagramSocket::BindType bind_type, | |
357 const RandIntCallback& rand_int_cb, | |
358 NetLog* net_log, | |
359 const NetLog::Source& source) OVERRIDE { | |
360 NOTREACHED(); | |
361 return scoped_ptr<DatagramClientSocket>(); | |
362 } | |
363 | |
364 virtual scoped_ptr<StreamSocket> CreateTransportClientSocket( | |
365 const AddressList& addresses, | |
366 NetLog* /* net_log */, | |
367 const NetLog::Source& /* source */) OVERRIDE { | |
368 allocation_count_++; | |
369 | |
370 ClientSocketType type = client_socket_type_; | |
371 if (client_socket_types_ && | |
372 client_socket_index_ < client_socket_index_max_) { | |
373 type = client_socket_types_[client_socket_index_++]; | |
374 } | |
375 | |
376 switch (type) { | |
377 case MOCK_CLIENT_SOCKET: | |
378 return scoped_ptr<StreamSocket>( | |
379 new MockClientSocket(addresses, net_log_)); | |
380 case MOCK_FAILING_CLIENT_SOCKET: | |
381 return scoped_ptr<StreamSocket>( | |
382 new MockFailingClientSocket(addresses, net_log_)); | |
383 case MOCK_PENDING_CLIENT_SOCKET: | |
384 return MockTriggerableClientSocket::MakeMockPendingClientSocket( | |
385 addresses, true, net_log_); | |
386 case MOCK_PENDING_FAILING_CLIENT_SOCKET: | |
387 return MockTriggerableClientSocket::MakeMockPendingClientSocket( | |
388 addresses, false, net_log_); | |
389 case MOCK_DELAYED_CLIENT_SOCKET: | |
390 return MockTriggerableClientSocket::MakeMockDelayedClientSocket( | |
391 addresses, true, delay_, net_log_); | |
392 case MOCK_DELAYED_FAILING_CLIENT_SOCKET: | |
393 return MockTriggerableClientSocket::MakeMockDelayedClientSocket( | |
394 addresses, false, delay_, net_log_); | |
395 case MOCK_STALLED_CLIENT_SOCKET: | |
396 return MockTriggerableClientSocket::MakeMockStalledClientSocket( | |
397 addresses, net_log_); | |
398 case MOCK_TRIGGERABLE_CLIENT_SOCKET: { | |
399 scoped_ptr<MockTriggerableClientSocket> rv( | |
400 new MockTriggerableClientSocket(addresses, true, net_log_)); | |
401 triggerable_sockets_.push(rv->GetConnectCallback()); | |
402 // run_loop_quit_closure_ behaves like a condition variable. It will | |
403 // wake up WaitForTriggerableSocketCreation() if it is sleeping. We | |
404 // don't need to worry about atomicity because this code is | |
405 // single-threaded. | |
406 if (!run_loop_quit_closure_.is_null()) | |
407 run_loop_quit_closure_.Run(); | |
408 return rv.PassAs<StreamSocket>(); | |
409 } | |
410 default: | |
411 NOTREACHED(); | |
412 return scoped_ptr<StreamSocket>( | |
413 new MockClientSocket(addresses, net_log_)); | |
414 } | |
415 } | |
416 | |
417 virtual scoped_ptr<SSLClientSocket> CreateSSLClientSocket( | |
418 scoped_ptr<ClientSocketHandle> transport_socket, | |
419 const HostPortPair& host_and_port, | |
420 const SSLConfig& ssl_config, | |
421 const SSLClientSocketContext& context) OVERRIDE { | |
422 NOTIMPLEMENTED(); | |
423 return scoped_ptr<SSLClientSocket>(); | |
424 } | |
425 | |
426 virtual void ClearSSLSessionCache() OVERRIDE { NOTIMPLEMENTED(); } | |
427 | |
428 int allocation_count() const { return allocation_count_; } | |
429 | |
430 // Set the default ClientSocketType. | |
431 void set_client_socket_type(ClientSocketType type) { | |
432 client_socket_type_ = type; | |
433 } | |
434 | |
435 // Set a list of ClientSocketTypes to be used. | |
436 void set_client_socket_types(ClientSocketType* type_list, int num_types) { | |
437 DCHECK_GT(num_types, 0); | |
438 client_socket_types_ = type_list; | |
439 client_socket_index_ = 0; | |
440 client_socket_index_max_ = num_types; | |
441 } | |
442 | |
443 void set_delay(base::TimeDelta delay) { delay_ = delay; } | |
444 | |
445 base::Closure WaitForTriggerableSocketCreation() { | |
446 while (triggerable_sockets_.empty()) { | |
447 base::RunLoop run_loop; | |
448 run_loop_quit_closure_ = run_loop.QuitClosure(); | |
449 run_loop.Run(); | |
450 run_loop_quit_closure_.Reset(); | |
451 } | |
452 base::Closure trigger = triggerable_sockets_.front(); | |
453 triggerable_sockets_.pop(); | |
454 return trigger; | |
455 } | |
456 | |
457 private: | |
458 NetLog* net_log_; | |
459 int allocation_count_; | |
460 ClientSocketType client_socket_type_; | |
461 ClientSocketType* client_socket_types_; | |
462 int client_socket_index_; | |
463 int client_socket_index_max_; | |
464 base::TimeDelta delay_; | |
465 std::queue<base::Closure> triggerable_sockets_; | |
466 base::Closure run_loop_quit_closure_; | |
467 | |
468 DISALLOW_COPY_AND_ASSIGN(MockClientSocketFactory); | |
469 }; | |
470 | |
471 class WebSocketTransportClientSocketPoolTest : public testing::Test { | |
472 protected: | |
473 WebSocketTransportClientSocketPoolTest() | |
474 : params_(new TransportSocketParams(HostPortPair("www.google.com", 80), | |
475 false, | |
476 false, | |
477 OnHostResolutionCallback())), | |
478 histograms_(new ClientSocketPoolHistograms("TCPUnitTest")), | |
479 host_resolver_(new MockHostResolver), | |
480 client_socket_factory_(&net_log_), | |
481 pool_(kMaxSockets, | |
482 kMaxSocketsPerGroup, | |
483 histograms_.get(), | |
484 host_resolver_.get(), | |
485 &client_socket_factory_, | |
486 NULL) {} | |
487 | |
488 virtual ~WebSocketTransportClientSocketPoolTest() {} | |
Johnny
2014/06/16 23:41:11
Verify that WebSocketEndpointLockManager is empty/
Adam Rice
2014/06/19 13:55:21
Done.
| |
489 | |
490 int StartRequest(const std::string& group_name, RequestPriority priority) { | |
491 scoped_refptr<TransportSocketParams> params( | |
492 new TransportSocketParams(HostPortPair("www.google.com", 80), | |
493 false, | |
494 false, | |
495 OnHostResolutionCallback())); | |
496 return test_base_.StartRequestUsingPool( | |
497 &pool_, group_name, priority, params); | |
498 } | |
499 | |
500 int GetOrderOfRequest(size_t index) { | |
501 return test_base_.GetOrderOfRequest(index); | |
502 } | |
503 | |
504 bool ReleaseOneConnection(ClientSocketPoolTest::KeepAlive keep_alive) { | |
505 return test_base_.ReleaseOneConnection(keep_alive); | |
506 } | |
507 | |
508 void ReleaseAllConnections(ClientSocketPoolTest::KeepAlive keep_alive) { | |
509 test_base_.ReleaseAllConnections(keep_alive); | |
510 } | |
511 | |
512 ScopedVector<TestSocketRequest>* requests() { return test_base_.requests(); } | |
513 size_t completion_count() const { return test_base_.completion_count(); } | |
514 | |
515 CapturingNetLog net_log_; | |
516 scoped_refptr<TransportSocketParams> params_; | |
517 scoped_ptr<ClientSocketPoolHistograms> histograms_; | |
518 scoped_ptr<MockHostResolver> host_resolver_; | |
519 MockClientSocketFactory client_socket_factory_; | |
520 WebSocketTransportClientSocketPool pool_; | |
521 ClientSocketPoolTest test_base_; | |
522 | |
523 private: | |
524 DISALLOW_COPY_AND_ASSIGN(WebSocketTransportClientSocketPoolTest); | |
525 }; | |
526 | |
527 TEST_F(WebSocketTransportClientSocketPoolTest, Basic) { | |
528 TestCompletionCallback callback; | |
529 ClientSocketHandle handle; | |
530 int rv = handle.Init( | |
531 "a", params_, LOW, callback.callback(), &pool_, BoundNetLog()); | |
532 EXPECT_EQ(ERR_IO_PENDING, rv); | |
533 EXPECT_FALSE(handle.is_initialized()); | |
534 EXPECT_FALSE(handle.socket()); | |
535 | |
536 EXPECT_EQ(OK, callback.WaitForResult()); | |
537 EXPECT_TRUE(handle.is_initialized()); | |
538 EXPECT_TRUE(handle.socket()); | |
539 TestLoadTimingInfoConnectedNotReused(handle); | |
540 } | |
541 | |
542 // Make sure that WebSocketTransportConnectJob passes on its priority to its | |
543 // HostResolver request on Init. | |
544 TEST_F(WebSocketTransportClientSocketPoolTest, SetResolvePriorityOnInit) { | |
545 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | |
546 RequestPriority priority = static_cast<RequestPriority>(i); | |
547 TestCompletionCallback callback; | |
548 ClientSocketHandle handle; | |
549 EXPECT_EQ(ERR_IO_PENDING, | |
550 handle.Init("a", | |
551 params_, | |
552 priority, | |
553 callback.callback(), | |
554 &pool_, | |
555 BoundNetLog())); | |
556 EXPECT_EQ(priority, host_resolver_->last_request_priority()); | |
557 } | |
558 } | |
559 | |
560 TEST_F(WebSocketTransportClientSocketPoolTest, InitHostResolutionFailure) { | |
561 host_resolver_->rules()->AddSimulatedFailure("unresolvable.host.name"); | |
562 TestCompletionCallback callback; | |
563 ClientSocketHandle handle; | |
564 HostPortPair host_port_pair("unresolvable.host.name", 80); | |
565 scoped_refptr<TransportSocketParams> dest(new TransportSocketParams( | |
566 host_port_pair, false, false, OnHostResolutionCallback())); | |
567 EXPECT_EQ(ERR_IO_PENDING, | |
568 handle.Init("a", | |
569 dest, | |
570 kDefaultPriority, | |
571 callback.callback(), | |
572 &pool_, | |
573 BoundNetLog())); | |
574 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback.WaitForResult()); | |
575 } | |
576 | |
577 TEST_F(WebSocketTransportClientSocketPoolTest, InitConnectionFailure) { | |
578 client_socket_factory_.set_client_socket_type( | |
579 MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET); | |
580 TestCompletionCallback callback; | |
581 ClientSocketHandle handle; | |
582 EXPECT_EQ(ERR_IO_PENDING, | |
583 handle.Init("a", | |
584 params_, | |
585 kDefaultPriority, | |
586 callback.callback(), | |
587 &pool_, | |
588 BoundNetLog())); | |
589 EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
590 | |
591 // Make the host resolutions complete synchronously this time. | |
592 host_resolver_->set_synchronous_mode(true); | |
593 EXPECT_EQ(ERR_CONNECTION_FAILED, | |
594 handle.Init("a", | |
595 params_, | |
596 kDefaultPriority, | |
597 callback.callback(), | |
598 &pool_, | |
599 BoundNetLog())); | |
600 } | |
601 | |
602 TEST_F(WebSocketTransportClientSocketPoolTest, PendingRequestsFinishFifo) { | |
603 // First request finishes asynchronously. | |
604 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
605 EXPECT_EQ(OK, (*requests())[0]->WaitForResult()); | |
606 | |
607 // Make all subsequent host resolutions complete synchronously. | |
608 host_resolver_->set_synchronous_mode(true); | |
609 | |
610 // Rest of them wait for the first socket to be released. | |
611 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
612 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
613 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
614 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
615 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
616 | |
617 ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE); | |
618 | |
619 EXPECT_EQ(6, client_socket_factory_.allocation_count()); | |
620 | |
621 // One initial asynchronous request and then 5 pending requests. | |
622 EXPECT_EQ(6U, completion_count()); | |
623 | |
624 // The requests finish in FIFO order. | |
625 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
626 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
627 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
628 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
629 EXPECT_EQ(5, GetOrderOfRequest(5)); | |
630 EXPECT_EQ(6, GetOrderOfRequest(6)); | |
631 | |
632 // Make sure we test order of all requests made. | |
633 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(7)); | |
634 } | |
635 | |
636 TEST_F(WebSocketTransportClientSocketPoolTest, PendingRequests_NoKeepAlive) { | |
637 // First request finishes asynchronously. | |
638 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
639 EXPECT_EQ(OK, (*requests())[0]->WaitForResult()); | |
640 | |
641 // Make all subsequent host resolutions complete synchronously. | |
642 host_resolver_->set_synchronous_mode(true); | |
643 | |
644 // Rest of them wait foe the first socket to be released. | |
645 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
646 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
647 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
648 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
649 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
650 | |
651 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
652 | |
653 // The pending requests should finish successfully. | |
654 EXPECT_EQ(OK, (*requests())[1]->WaitForResult()); | |
655 EXPECT_EQ(OK, (*requests())[2]->WaitForResult()); | |
656 EXPECT_EQ(OK, (*requests())[3]->WaitForResult()); | |
657 EXPECT_EQ(OK, (*requests())[4]->WaitForResult()); | |
658 EXPECT_EQ(OK, (*requests())[5]->WaitForResult()); | |
659 | |
660 EXPECT_EQ(static_cast<int>(requests()->size()), | |
661 client_socket_factory_.allocation_count()); | |
662 | |
663 // First asynchronous request, and then last 5 pending requests. | |
664 EXPECT_EQ(6U, completion_count()); | |
665 } | |
666 | |
667 // This test will start up a RequestSocket() and then immediately Cancel() it. | |
668 // The pending host resolution will eventually complete, and destroy the | |
669 // ClientSocketPool which will crash if the group was not cleared properly. | |
670 TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequestClearGroup) { | |
671 TestCompletionCallback callback; | |
672 ClientSocketHandle handle; | |
673 EXPECT_EQ(ERR_IO_PENDING, | |
674 handle.Init("a", | |
675 params_, | |
676 kDefaultPriority, | |
677 callback.callback(), | |
678 &pool_, | |
679 BoundNetLog())); | |
680 handle.Reset(); | |
681 } | |
682 | |
683 TEST_F(WebSocketTransportClientSocketPoolTest, TwoRequestsCancelOne) { | |
684 ClientSocketHandle handle; | |
685 TestCompletionCallback callback; | |
686 ClientSocketHandle handle2; | |
687 TestCompletionCallback callback2; | |
688 | |
689 EXPECT_EQ(ERR_IO_PENDING, | |
690 handle.Init("a", | |
691 params_, | |
692 kDefaultPriority, | |
693 callback.callback(), | |
694 &pool_, | |
695 BoundNetLog())); | |
696 EXPECT_EQ(ERR_IO_PENDING, | |
697 handle2.Init("a", | |
698 params_, | |
699 kDefaultPriority, | |
700 callback2.callback(), | |
701 &pool_, | |
702 BoundNetLog())); | |
703 | |
704 handle.Reset(); | |
705 | |
706 EXPECT_EQ(OK, callback2.WaitForResult()); | |
707 handle2.Reset(); | |
708 } | |
709 | |
710 TEST_F(WebSocketTransportClientSocketPoolTest, ConnectCancelConnect) { | |
711 client_socket_factory_.set_client_socket_type( | |
712 MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET); | |
713 ClientSocketHandle handle; | |
714 TestCompletionCallback callback; | |
715 EXPECT_EQ(ERR_IO_PENDING, | |
716 handle.Init("a", | |
717 params_, | |
718 kDefaultPriority, | |
719 callback.callback(), | |
720 &pool_, | |
721 BoundNetLog())); | |
722 | |
723 handle.Reset(); | |
724 | |
725 TestCompletionCallback callback2; | |
726 EXPECT_EQ(ERR_IO_PENDING, | |
727 handle.Init("a", | |
728 params_, | |
729 kDefaultPriority, | |
730 callback2.callback(), | |
731 &pool_, | |
732 BoundNetLog())); | |
733 | |
734 host_resolver_->set_synchronous_mode(true); | |
735 // At this point, handle has two ConnectingSockets out for it. Due to the | |
736 // setting the mock resolver into synchronous mode, the host resolution for | |
737 // both will return in the same loop of the MessageLoop. The client socket | |
738 // is a pending socket, so the Connect() will asynchronously complete on the | |
739 // next loop of the MessageLoop. That means that the first | |
740 // ConnectingSocket will enter OnIOComplete, and then the second one will. | |
741 // If the first one is not cancelled, it will advance the load state, and | |
742 // then the second one will crash. | |
743 | |
744 EXPECT_EQ(OK, callback2.WaitForResult()); | |
745 EXPECT_FALSE(callback.have_result()); | |
746 | |
747 handle.Reset(); | |
748 } | |
749 | |
750 TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequest) { | |
751 // First request finishes asynchronously. | |
752 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
753 EXPECT_EQ(OK, (*requests())[0]->WaitForResult()); | |
754 | |
755 // Make all subsequent host resolutions complete synchronously. | |
756 host_resolver_->set_synchronous_mode(true); | |
757 | |
758 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
759 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
760 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
761 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
762 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
763 | |
764 // Cancel a request. | |
765 const size_t index_to_cancel = 2; | |
766 EXPECT_FALSE((*requests())[index_to_cancel]->handle()->is_initialized()); | |
767 (*requests())[index_to_cancel]->handle()->Reset(); | |
768 | |
769 ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE); | |
770 | |
771 EXPECT_EQ(5, client_socket_factory_.allocation_count()); | |
772 | |
773 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
774 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
775 EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, | |
776 GetOrderOfRequest(3)); // Canceled request. | |
777 EXPECT_EQ(3, GetOrderOfRequest(4)); | |
778 EXPECT_EQ(4, GetOrderOfRequest(5)); | |
779 EXPECT_EQ(5, GetOrderOfRequest(6)); | |
780 | |
781 // Make sure we test order of all requests made. | |
782 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(7)); | |
783 } | |
784 | |
785 class RequestSocketCallback : public TestCompletionCallbackBase { | |
786 public: | |
787 RequestSocketCallback(ClientSocketHandle* handle, | |
788 WebSocketTransportClientSocketPool* pool) | |
789 : handle_(handle), | |
790 pool_(pool), | |
791 within_callback_(false), | |
792 callback_(base::Bind(&RequestSocketCallback::OnComplete, | |
793 base::Unretained(this))) {} | |
794 | |
795 virtual ~RequestSocketCallback() {} | |
796 | |
797 const CompletionCallback& callback() const { return callback_; } | |
798 | |
799 private: | |
800 void OnComplete(int result) { | |
801 SetResult(result); | |
802 ASSERT_EQ(OK, result); | |
803 | |
804 if (!within_callback_) { | |
805 // Don't allow reuse of the socket. Disconnect it and then release it and | |
806 // run through the MessageLoop once to get it completely released. | |
807 handle_->socket()->Disconnect(); | |
808 handle_->Reset(); | |
809 { | |
810 base::MessageLoop::ScopedNestableTaskAllower allow( | |
811 base::MessageLoop::current()); | |
812 base::MessageLoop::current()->RunUntilIdle(); | |
813 } | |
814 within_callback_ = true; | |
815 scoped_refptr<TransportSocketParams> dest( | |
816 new TransportSocketParams(HostPortPair("www.google.com", 80), | |
817 false, | |
818 false, | |
819 OnHostResolutionCallback())); | |
820 int rv = | |
821 handle_->Init("a", dest, LOWEST, callback(), pool_, BoundNetLog()); | |
822 EXPECT_EQ(OK, rv); | |
823 } | |
824 } | |
825 | |
826 ClientSocketHandle* const handle_; | |
827 WebSocketTransportClientSocketPool* const pool_; | |
828 bool within_callback_; | |
829 CompletionCallback callback_; | |
830 | |
831 DISALLOW_COPY_AND_ASSIGN(RequestSocketCallback); | |
832 }; | |
833 | |
834 TEST_F(WebSocketTransportClientSocketPoolTest, RequestTwice) { | |
835 ClientSocketHandle handle; | |
836 RequestSocketCallback callback(&handle, &pool_); | |
837 scoped_refptr<TransportSocketParams> dest( | |
838 new TransportSocketParams(HostPortPair("www.google.com", 80), | |
839 false, | |
840 false, | |
841 OnHostResolutionCallback())); | |
842 int rv = handle.Init( | |
843 "a", dest, LOWEST, callback.callback(), &pool_, BoundNetLog()); | |
844 ASSERT_EQ(ERR_IO_PENDING, rv); | |
845 | |
846 // The callback is going to request "www.google.com". We want it to complete | |
847 // synchronously this time. | |
848 host_resolver_->set_synchronous_mode(true); | |
849 | |
850 EXPECT_EQ(OK, callback.WaitForResult()); | |
851 | |
852 handle.Reset(); | |
853 } | |
854 | |
855 // Make sure that pending requests get serviced after active requests get | |
856 // cancelled. | |
857 TEST_F(WebSocketTransportClientSocketPoolTest, | |
858 CancelActiveRequestWithPendingRequests) { | |
859 client_socket_factory_.set_client_socket_type( | |
860 MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET); | |
861 | |
862 // Queue up all the requests | |
863 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
864 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
865 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
866 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
867 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
868 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
869 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
870 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
871 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
872 | |
873 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. | |
874 ASSERT_LE(kMaxSocketsPerGroup, static_cast<int>(requests()->size())); | |
875 for (int i = 0; i < kMaxSocketsPerGroup; i++) | |
876 (*requests())[i]->handle()->Reset(); | |
877 | |
878 // Let's wait for the rest to complete now. | |
879 for (size_t i = kMaxSocketsPerGroup; i < requests()->size(); ++i) { | |
880 EXPECT_EQ(OK, (*requests())[i]->WaitForResult()); | |
881 (*requests())[i]->handle()->Reset(); | |
882 } | |
883 | |
884 EXPECT_EQ(requests()->size() - kMaxSocketsPerGroup, completion_count()); | |
885 } | |
886 | |
887 // Make sure that pending requests get serviced after active requests fail. | |
888 TEST_F(WebSocketTransportClientSocketPoolTest, | |
889 FailingActiveRequestWithPendingRequests) { | |
890 client_socket_factory_.set_client_socket_type( | |
891 MockClientSocketFactory::MOCK_PENDING_FAILING_CLIENT_SOCKET); | |
892 | |
893 const int kNumRequests = 2 * kMaxSocketsPerGroup + 1; | |
894 ASSERT_LE(kNumRequests, kMaxSockets); // Otherwise the test will hang. | |
895 | |
896 // Queue up all the requests | |
897 for (int i = 0; i < kNumRequests; i++) | |
898 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
899 | |
900 for (int i = 0; i < kNumRequests; i++) | |
901 EXPECT_EQ(ERR_CONNECTION_FAILED, (*requests())[i]->WaitForResult()); | |
902 } | |
903 | |
904 // The lock on the endpoint is released when a ClientSocketHandle is reset. | |
905 TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleReset) { | |
906 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
907 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
908 EXPECT_EQ(OK, (*requests())[0]->WaitForResult()); | |
909 EXPECT_FALSE((*requests())[1]->handle()->is_initialized()); | |
910 (*requests())[0]->handle()->Reset(); | |
911 base::RunLoop().RunUntilIdle(); | |
912 EXPECT_TRUE((*requests())[1]->handle()->is_initialized()); | |
913 } | |
914 | |
915 // The lock on the endpoint is released when a ClientSocketHandle is deleted. | |
916 TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleDelete) { | |
917 TestCompletionCallback callback; | |
918 scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle); | |
919 int rv = handle->Init( | |
920 "a", params_, LOW, callback.callback(), &pool_, BoundNetLog()); | |
921 EXPECT_EQ(ERR_IO_PENDING, rv); | |
922 | |
923 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
924 EXPECT_EQ(OK, callback.WaitForResult()); | |
925 EXPECT_FALSE((*requests())[0]->handle()->is_initialized()); | |
926 handle.reset(); | |
927 base::RunLoop().RunUntilIdle(); | |
928 EXPECT_TRUE((*requests())[0]->handle()->is_initialized()); | |
929 } | |
930 | |
931 // A new connection is performed when the lock on the previous connection is | |
932 // explicity released. | |
933 TEST_F(WebSocketTransportClientSocketPoolTest, | |
934 ConnectionProceedsOnExplicitRelease) { | |
935 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
936 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
937 EXPECT_EQ(OK, (*requests())[0]->WaitForResult()); | |
938 EXPECT_FALSE((*requests())[1]->handle()->is_initialized()); | |
939 WebSocketTransportClientSocketPool::UnlockEndpoint( | |
940 (*requests())[0]->handle()); | |
941 base::RunLoop().RunUntilIdle(); | |
942 EXPECT_TRUE((*requests())[1]->handle()->is_initialized()); | |
943 } | |
944 | |
945 // A connection which is cancelled before completion does not block subsequent | |
946 // connections. | |
947 TEST_F(WebSocketTransportClientSocketPoolTest, | |
948 CancelDuringConnectionReleasesLock) { | |
949 MockClientSocketFactory::ClientSocketType case_types[] = { | |
950 MockClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET, | |
951 MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET}; | |
952 | |
953 client_socket_factory_.set_client_socket_types(case_types, | |
954 arraysize(case_types)); | |
955 | |
956 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
957 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
958 base::RunLoop().RunUntilIdle(); | |
959 pool_.CancelRequest("a", ((*requests())[0])->handle()); | |
960 EXPECT_EQ(OK, (*requests())[1]->WaitForResult()); | |
961 } | |
962 | |
963 // Test the case of the IPv6 address stalling, and falling back to the IPv4 | |
964 // socket which finishes first. | |
965 TEST_F(WebSocketTransportClientSocketPoolTest, | |
966 IPv6FallbackSocketIPv4FinishesFirst) { | |
967 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
968 kMaxSocketsPerGroup, | |
969 histograms_.get(), | |
970 host_resolver_.get(), | |
971 &client_socket_factory_, | |
972 NULL); | |
973 | |
974 MockClientSocketFactory::ClientSocketType case_types[] = { | |
975 // This is the IPv6 socket. | |
976 MockClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET, | |
977 // This is the IPv4 socket. | |
978 MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET}; | |
979 | |
980 client_socket_factory_.set_client_socket_types(case_types, 2); | |
981 | |
982 // Resolve an AddressList with a IPv6 address first and then a IPv4 address. | |
983 host_resolver_->rules()->AddIPLiteralRule( | |
984 "*", "2:abcd::3:4:ff,2.2.2.2", std::string()); | |
985 | |
986 TestCompletionCallback callback; | |
987 ClientSocketHandle handle; | |
988 int rv = | |
989 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
990 EXPECT_EQ(ERR_IO_PENDING, rv); | |
991 EXPECT_FALSE(handle.is_initialized()); | |
992 EXPECT_FALSE(handle.socket()); | |
993 | |
994 EXPECT_EQ(OK, callback.WaitForResult()); | |
995 EXPECT_TRUE(handle.is_initialized()); | |
996 EXPECT_TRUE(handle.socket()); | |
997 IPEndPoint endpoint; | |
998 handle.socket()->GetLocalAddress(&endpoint); | |
999 EXPECT_EQ(kIPv4AddressSize, endpoint.address().size()); | |
1000 EXPECT_EQ(2, client_socket_factory_.allocation_count()); | |
1001 } | |
1002 | |
1003 // Test the case of the IPv6 address being slow, thus falling back to trying to | |
1004 // connect to the IPv4 address, but having the connect to the IPv6 address | |
1005 // finish first. | |
1006 TEST_F(WebSocketTransportClientSocketPoolTest, | |
1007 IPv6FallbackSocketIPv6FinishesFirst) { | |
1008 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1009 kMaxSocketsPerGroup, | |
1010 histograms_.get(), | |
1011 host_resolver_.get(), | |
1012 &client_socket_factory_, | |
1013 NULL); | |
1014 | |
1015 MockClientSocketFactory::ClientSocketType case_types[] = { | |
1016 // This is the IPv6 socket. | |
1017 MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET, | |
1018 // This is the IPv4 socket. | |
1019 MockClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET}; | |
1020 | |
1021 client_socket_factory_.set_client_socket_types(case_types, 2); | |
1022 client_socket_factory_.set_delay(base::TimeDelta::FromMilliseconds( | |
1023 TransportConnectJobHelper::kIPv6FallbackTimerInMs + 50)); | |
1024 | |
1025 // Resolve an AddressList with a IPv6 address first and then a IPv4 address. | |
1026 host_resolver_->rules()->AddIPLiteralRule( | |
1027 "*", "2:abcd::3:4:ff,2.2.2.2", std::string()); | |
1028 | |
1029 TestCompletionCallback callback; | |
1030 ClientSocketHandle handle; | |
1031 int rv = | |
1032 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1033 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1034 EXPECT_FALSE(handle.is_initialized()); | |
1035 EXPECT_FALSE(handle.socket()); | |
1036 | |
1037 EXPECT_EQ(OK, callback.WaitForResult()); | |
1038 EXPECT_TRUE(handle.is_initialized()); | |
1039 EXPECT_TRUE(handle.socket()); | |
1040 IPEndPoint endpoint; | |
1041 handle.socket()->GetLocalAddress(&endpoint); | |
1042 EXPECT_EQ(kIPv6AddressSize, endpoint.address().size()); | |
1043 EXPECT_EQ(2, client_socket_factory_.allocation_count()); | |
1044 } | |
1045 | |
1046 TEST_F(WebSocketTransportClientSocketPoolTest, | |
1047 IPv6NoIPv4AddressesToFallbackTo) { | |
1048 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1049 kMaxSocketsPerGroup, | |
1050 histograms_.get(), | |
1051 host_resolver_.get(), | |
1052 &client_socket_factory_, | |
1053 NULL); | |
1054 | |
1055 client_socket_factory_.set_client_socket_type( | |
1056 MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET); | |
1057 | |
1058 // Resolve an AddressList with only IPv6 addresses. | |
1059 host_resolver_->rules()->AddIPLiteralRule( | |
1060 "*", "2:abcd::3:4:ff,3:abcd::3:4:ff", std::string()); | |
1061 | |
1062 TestCompletionCallback callback; | |
1063 ClientSocketHandle handle; | |
1064 int rv = | |
1065 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1066 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1067 EXPECT_FALSE(handle.is_initialized()); | |
1068 EXPECT_FALSE(handle.socket()); | |
1069 | |
1070 EXPECT_EQ(OK, callback.WaitForResult()); | |
1071 EXPECT_TRUE(handle.is_initialized()); | |
1072 EXPECT_TRUE(handle.socket()); | |
1073 IPEndPoint endpoint; | |
1074 handle.socket()->GetLocalAddress(&endpoint); | |
1075 EXPECT_EQ(kIPv6AddressSize, endpoint.address().size()); | |
1076 EXPECT_EQ(1, client_socket_factory_.allocation_count()); | |
1077 } | |
1078 | |
1079 TEST_F(WebSocketTransportClientSocketPoolTest, IPv4HasNoFallback) { | |
1080 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1081 kMaxSocketsPerGroup, | |
1082 histograms_.get(), | |
1083 host_resolver_.get(), | |
1084 &client_socket_factory_, | |
1085 NULL); | |
1086 | |
1087 client_socket_factory_.set_client_socket_type( | |
1088 MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET); | |
1089 | |
1090 // Resolve an AddressList with only IPv4 addresses. | |
1091 host_resolver_->rules()->AddIPLiteralRule("*", "1.1.1.1", std::string()); | |
1092 | |
1093 TestCompletionCallback callback; | |
1094 ClientSocketHandle handle; | |
1095 int rv = | |
1096 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1097 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1098 EXPECT_FALSE(handle.is_initialized()); | |
1099 EXPECT_FALSE(handle.socket()); | |
1100 | |
1101 EXPECT_EQ(OK, callback.WaitForResult()); | |
1102 EXPECT_TRUE(handle.is_initialized()); | |
1103 EXPECT_TRUE(handle.socket()); | |
1104 IPEndPoint endpoint; | |
1105 handle.socket()->GetLocalAddress(&endpoint); | |
1106 EXPECT_EQ(kIPv4AddressSize, endpoint.address().size()); | |
1107 EXPECT_EQ(1, client_socket_factory_.allocation_count()); | |
1108 } | |
1109 | |
1110 // If all IPv6 addresses fail to connect synchronously, then IPv4 connections | |
1111 // proceeed immediately. | |
1112 TEST_F(WebSocketTransportClientSocketPoolTest, IPv6InstantFail) { | |
1113 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1114 kMaxSocketsPerGroup, | |
1115 histograms_.get(), | |
1116 host_resolver_.get(), | |
1117 &client_socket_factory_, | |
1118 NULL); | |
1119 | |
1120 MockClientSocketFactory::ClientSocketType case_types[] = { | |
1121 // First IPv6 socket. | |
1122 MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET, | |
1123 // Second IPv6 socket. | |
1124 MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET, | |
1125 // This is the IPv4 socket. | |
1126 MockClientSocketFactory::MOCK_CLIENT_SOCKET}; | |
1127 | |
1128 client_socket_factory_.set_client_socket_types(case_types, | |
1129 arraysize(case_types)); | |
1130 | |
1131 // Resolve an AddressList with two IPv6 addresses and then a IPv4 address. | |
1132 host_resolver_->rules()->AddIPLiteralRule( | |
1133 "*", "2:abcd::3:4:ff,2:abcd::3:5:ff,2.2.2.2", std::string()); | |
1134 host_resolver_->set_synchronous_mode(true); | |
1135 TestCompletionCallback callback; | |
1136 ClientSocketHandle handle; | |
1137 int rv = | |
1138 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1139 EXPECT_EQ(OK, rv); | |
1140 ASSERT_TRUE(handle.socket()); | |
1141 | |
1142 IPEndPoint endpoint; | |
1143 handle.socket()->GetPeerAddress(&endpoint); | |
1144 EXPECT_EQ("2.2.2.2", endpoint.ToStringWithoutPort()); | |
1145 } | |
1146 | |
1147 // If all IPv6 addresses fail before the IPv4 fallback timeout, then the IPv4 | |
1148 // connections proceed immediately. | |
1149 TEST_F(WebSocketTransportClientSocketPoolTest, IPv6RapidFail) { | |
1150 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1151 kMaxSocketsPerGroup, | |
1152 histograms_.get(), | |
1153 host_resolver_.get(), | |
1154 &client_socket_factory_, | |
1155 NULL); | |
1156 | |
1157 MockClientSocketFactory::ClientSocketType case_types[] = { | |
1158 // First IPv6 socket. | |
1159 MockClientSocketFactory::MOCK_PENDING_FAILING_CLIENT_SOCKET, | |
1160 // Second IPv6 socket. | |
1161 MockClientSocketFactory::MOCK_PENDING_FAILING_CLIENT_SOCKET, | |
1162 // This is the IPv4 socket. | |
1163 MockClientSocketFactory::MOCK_CLIENT_SOCKET}; | |
1164 | |
1165 client_socket_factory_.set_client_socket_types(case_types, | |
1166 arraysize(case_types)); | |
1167 | |
1168 // Resolve an AddressList with two IPv6 addresses and then a IPv4 address. | |
1169 host_resolver_->rules()->AddIPLiteralRule( | |
1170 "*", "2:abcd::3:4:ff,2:abcd::3:5:ff,2.2.2.2", std::string()); | |
1171 | |
1172 TestCompletionCallback callback; | |
1173 ClientSocketHandle handle; | |
1174 int rv = | |
1175 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1176 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1177 EXPECT_FALSE(handle.socket()); | |
1178 | |
1179 base::Time start(base::Time::NowFromSystemTime()); | |
1180 EXPECT_EQ(OK, callback.WaitForResult()); | |
1181 EXPECT_LT(base::Time::NowFromSystemTime() - start, | |
1182 base::TimeDelta::FromMilliseconds( | |
1183 TransportConnectJobHelper::kIPv6FallbackTimerInMs)); | |
1184 ASSERT_TRUE(handle.socket()); | |
1185 | |
1186 IPEndPoint endpoint; | |
1187 handle.socket()->GetPeerAddress(&endpoint); | |
1188 EXPECT_EQ("2.2.2.2", endpoint.ToStringWithoutPort()); | |
1189 } | |
1190 | |
1191 // If two sockets connect successfully, the one which connected first wins (this | |
1192 // can only happen if the sockets are different types, since sockets of the same | |
1193 // type do not race). | |
1194 TEST_F(WebSocketTransportClientSocketPoolTest, FirstSuccessWins) { | |
1195 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1196 kMaxSocketsPerGroup, | |
1197 histograms_.get(), | |
1198 host_resolver_.get(), | |
1199 &client_socket_factory_, | |
1200 NULL); | |
1201 | |
1202 client_socket_factory_.set_client_socket_type( | |
1203 MockClientSocketFactory::MOCK_TRIGGERABLE_CLIENT_SOCKET); | |
1204 | |
1205 // Resolve an AddressList with an IPv6 addresses and an IPv4 address. | |
1206 host_resolver_->rules()->AddIPLiteralRule( | |
1207 "*", "2:abcd::3:4:ff,2.2.2.2", std::string()); | |
1208 | |
1209 TestCompletionCallback callback; | |
1210 ClientSocketHandle handle; | |
1211 int rv = | |
1212 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1213 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1214 ASSERT_FALSE(handle.socket()); | |
1215 | |
1216 base::Closure ipv6_connect_trigger = | |
1217 client_socket_factory_.WaitForTriggerableSocketCreation(); | |
1218 base::Closure ipv4_connect_trigger = | |
1219 client_socket_factory_.WaitForTriggerableSocketCreation(); | |
1220 | |
1221 ipv4_connect_trigger.Run(); | |
1222 ipv6_connect_trigger.Run(); | |
1223 | |
1224 EXPECT_EQ(OK, callback.WaitForResult()); | |
1225 ASSERT_TRUE(handle.socket()); | |
1226 | |
1227 IPEndPoint endpoint; | |
1228 handle.socket()->GetPeerAddress(&endpoint); | |
1229 EXPECT_EQ("2.2.2.2", endpoint.ToStringWithoutPort()); | |
1230 } | |
1231 | |
1232 // We should not report failure until all connections have failed. | |
1233 TEST_F(WebSocketTransportClientSocketPoolTest, LastFailureWins) { | |
1234 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1235 kMaxSocketsPerGroup, | |
1236 histograms_.get(), | |
1237 host_resolver_.get(), | |
1238 &client_socket_factory_, | |
1239 NULL); | |
1240 | |
1241 client_socket_factory_.set_client_socket_type( | |
1242 MockClientSocketFactory::MOCK_DELAYED_FAILING_CLIENT_SOCKET); | |
1243 base::TimeDelta delay = base::TimeDelta::FromMilliseconds( | |
1244 TransportConnectJobHelper::kIPv6FallbackTimerInMs / 3); | |
1245 client_socket_factory_.set_delay(delay); | |
1246 | |
1247 // Resolve an AddressList with 4 IPv6 addresses and 2 IPv4 address. | |
1248 host_resolver_->rules()->AddIPLiteralRule("*", | |
1249 "1:abcd::3:4:ff,2:abcd::3:4:ff," | |
1250 "3:abcd::3:4:ff,4:abcd::3:4:ff," | |
1251 "1.1.1.1,2.2.2.2", | |
1252 std::string()); | |
1253 | |
1254 // Expected order of events: | |
1255 // After 100ms: Connect to 1:abcd::3:4:ff times out | |
1256 // After 200ms: Connect to 2:abcd::3:4:ff times out | |
1257 // After 300ms: Connect to 3:abcd::3:4:ff times out, IPv4 fallback starts | |
1258 // After 400ms: Connect to 4:abcd::3:4:ff and 1.1.1.1 time out | |
1259 // After 500ms: Connect to 2.2.2.2 times out | |
1260 | |
1261 TestCompletionCallback callback; | |
1262 ClientSocketHandle handle; | |
1263 base::Time start(base::Time::NowFromSystemTime()); | |
1264 int rv = | |
1265 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1266 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1267 | |
1268 EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
1269 | |
1270 EXPECT_GE(base::Time::NowFromSystemTime() - start, delay * 5); | |
1271 } | |
1272 | |
1273 // Global timeout for all connects applies. This test is disabled by default | |
1274 // because it takes 4 minutes. Run with --gtest_also_run_disabled_tests if you | |
1275 // want to run it. | |
1276 TEST_F(WebSocketTransportClientSocketPoolTest, DISABLED_OverallTimeoutApplies) { | |
1277 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
1278 kMaxSocketsPerGroup, | |
1279 histograms_.get(), | |
1280 host_resolver_.get(), | |
1281 &client_socket_factory_, | |
1282 NULL); | |
1283 const base::TimeDelta connect_job_timeout = pool.ConnectionTimeout(); | |
1284 | |
1285 client_socket_factory_.set_client_socket_type( | |
1286 MockClientSocketFactory::MOCK_DELAYED_FAILING_CLIENT_SOCKET); | |
1287 client_socket_factory_.set_delay(base::TimeDelta::FromSeconds(1) + | |
1288 connect_job_timeout / 6); | |
1289 | |
1290 // Resolve an AddressList with 6 IPv6 addresses and 6 IPv4 address. | |
1291 host_resolver_->rules()->AddIPLiteralRule("*", | |
1292 "1:abcd::3:4:ff,2:abcd::3:4:ff," | |
1293 "3:abcd::3:4:ff,4:abcd::3:4:ff," | |
1294 "5:abcd::3:4:ff,6:abcd::3:4:ff," | |
1295 "1.1.1.1,2.2.2.2,3.3.3.3," | |
1296 "4.4.4.4,5.5.5.5,6.6.6.6", | |
1297 std::string()); | |
1298 | |
1299 TestCompletionCallback callback; | |
1300 ClientSocketHandle handle; | |
1301 | |
1302 int rv = | |
1303 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
1304 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1305 | |
1306 EXPECT_EQ(ERR_TIMED_OUT, callback.WaitForResult()); | |
1307 } | |
1308 | |
1309 } // namespace | |
1310 | |
1311 } // namespace net | |
OLD | NEW |