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 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/callback.h" | |
13 #include "base/macros.h" | |
14 #include "base/message_loop/message_loop.h" | |
15 #include "base/run_loop.h" | |
16 #include "base/strings/stringprintf.h" | |
17 #include "base/time/time.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_handle.h" | |
27 #include "net/socket/client_socket_pool_histograms.h" | |
28 #include "net/socket/socket_test_util.h" | |
29 #include "net/socket/stream_socket.h" | |
30 #include "net/socket/transport_client_socket_pool_test_util.h" | |
31 #include "net/socket/websocket_endpoint_lock_manager.h" | |
32 #include "testing/gtest/include/gtest/gtest.h" | |
33 | |
34 namespace net { | |
35 | |
36 namespace { | |
37 | |
38 const int kMaxSockets = 32; | |
39 const int kMaxSocketsPerGroup = 6; | |
40 const RequestPriority kDefaultPriority = LOW; | |
41 | |
42 // RunLoop doesn't support this natively but it is easy to emulate. | |
43 void RunLoopForTimePeriod(base::TimeDelta period) { | |
44 base::RunLoop run_loop; | |
45 base::Closure quit_closure(run_loop.QuitClosure()); | |
46 base::MessageLoop::current()->PostDelayedTask( | |
47 FROM_HERE, quit_closure, period); | |
48 run_loop.Run(); | |
49 } | |
50 | |
51 class WebSocketTransportClientSocketPoolTest : public ::testing::Test { | |
52 protected: | |
53 WebSocketTransportClientSocketPoolTest() | |
54 : params_(new TransportSocketParams( | |
55 HostPortPair("www.google.com", 80), | |
56 false, | |
57 false, | |
58 OnHostResolutionCallback(), | |
59 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)), | |
60 histograms_(new ClientSocketPoolHistograms("TCPUnitTest")), | |
61 host_resolver_(new MockHostResolver), | |
62 client_socket_factory_(&net_log_), | |
63 pool_(kMaxSockets, | |
64 kMaxSocketsPerGroup, | |
65 histograms_.get(), | |
66 host_resolver_.get(), | |
67 &client_socket_factory_, | |
68 NULL) {} | |
69 | |
70 ~WebSocketTransportClientSocketPoolTest() override { | |
71 RunUntilIdle(); | |
72 // ReleaseAllConnections() calls RunUntilIdle() after releasing each | |
73 // connection. | |
74 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
75 EXPECT_TRUE(WebSocketEndpointLockManager::GetInstance()->IsEmpty()); | |
76 } | |
77 | |
78 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } | |
79 | |
80 int StartRequest(const std::string& group_name, RequestPriority priority) { | |
81 scoped_refptr<TransportSocketParams> params( | |
82 new TransportSocketParams( | |
83 HostPortPair("www.google.com", 80), | |
84 false, | |
85 false, | |
86 OnHostResolutionCallback(), | |
87 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); | |
88 return test_base_.StartRequestUsingPool( | |
89 &pool_, group_name, priority, params); | |
90 } | |
91 | |
92 int GetOrderOfRequest(size_t index) { | |
93 return test_base_.GetOrderOfRequest(index); | |
94 } | |
95 | |
96 bool ReleaseOneConnection(ClientSocketPoolTest::KeepAlive keep_alive) { | |
97 return test_base_.ReleaseOneConnection(keep_alive); | |
98 } | |
99 | |
100 void ReleaseAllConnections(ClientSocketPoolTest::KeepAlive keep_alive) { | |
101 test_base_.ReleaseAllConnections(keep_alive); | |
102 } | |
103 | |
104 TestSocketRequest* request(int i) { return test_base_.request(i); } | |
105 | |
106 ScopedVector<TestSocketRequest>* requests() { return test_base_.requests(); } | |
107 size_t completion_count() const { return test_base_.completion_count(); } | |
108 | |
109 CapturingNetLog net_log_; | |
110 scoped_refptr<TransportSocketParams> params_; | |
111 scoped_ptr<ClientSocketPoolHistograms> histograms_; | |
112 scoped_ptr<MockHostResolver> host_resolver_; | |
113 MockTransportClientSocketFactory client_socket_factory_; | |
114 WebSocketTransportClientSocketPool pool_; | |
115 ClientSocketPoolTest test_base_; | |
116 ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_; | |
117 | |
118 private: | |
119 DISALLOW_COPY_AND_ASSIGN(WebSocketTransportClientSocketPoolTest); | |
120 }; | |
121 | |
122 TEST_F(WebSocketTransportClientSocketPoolTest, Basic) { | |
123 TestCompletionCallback callback; | |
124 ClientSocketHandle handle; | |
125 int rv = handle.Init( | |
126 "a", params_, LOW, callback.callback(), &pool_, BoundNetLog()); | |
127 EXPECT_EQ(ERR_IO_PENDING, rv); | |
128 EXPECT_FALSE(handle.is_initialized()); | |
129 EXPECT_FALSE(handle.socket()); | |
130 | |
131 EXPECT_EQ(OK, callback.WaitForResult()); | |
132 EXPECT_TRUE(handle.is_initialized()); | |
133 EXPECT_TRUE(handle.socket()); | |
134 TestLoadTimingInfoConnectedNotReused(handle); | |
135 } | |
136 | |
137 // Make sure that WebSocketTransportConnectJob passes on its priority to its | |
138 // HostResolver request on Init. | |
139 TEST_F(WebSocketTransportClientSocketPoolTest, SetResolvePriorityOnInit) { | |
140 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | |
141 RequestPriority priority = static_cast<RequestPriority>(i); | |
142 TestCompletionCallback callback; | |
143 ClientSocketHandle handle; | |
144 EXPECT_EQ(ERR_IO_PENDING, | |
145 handle.Init("a", | |
146 params_, | |
147 priority, | |
148 callback.callback(), | |
149 &pool_, | |
150 BoundNetLog())); | |
151 EXPECT_EQ(priority, host_resolver_->last_request_priority()); | |
152 } | |
153 } | |
154 | |
155 TEST_F(WebSocketTransportClientSocketPoolTest, InitHostResolutionFailure) { | |
156 host_resolver_->rules()->AddSimulatedFailure("unresolvable.host.name"); | |
157 TestCompletionCallback callback; | |
158 ClientSocketHandle handle; | |
159 HostPortPair host_port_pair("unresolvable.host.name", 80); | |
160 scoped_refptr<TransportSocketParams> dest(new TransportSocketParams( | |
161 host_port_pair, false, false, OnHostResolutionCallback(), | |
162 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); | |
163 EXPECT_EQ(ERR_IO_PENDING, | |
164 handle.Init("a", | |
165 dest, | |
166 kDefaultPriority, | |
167 callback.callback(), | |
168 &pool_, | |
169 BoundNetLog())); | |
170 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback.WaitForResult()); | |
171 } | |
172 | |
173 TEST_F(WebSocketTransportClientSocketPoolTest, InitConnectionFailure) { | |
174 client_socket_factory_.set_default_client_socket_type( | |
175 MockTransportClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET); | |
176 TestCompletionCallback callback; | |
177 ClientSocketHandle handle; | |
178 EXPECT_EQ(ERR_IO_PENDING, | |
179 handle.Init("a", | |
180 params_, | |
181 kDefaultPriority, | |
182 callback.callback(), | |
183 &pool_, | |
184 BoundNetLog())); | |
185 EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
186 | |
187 // Make the host resolutions complete synchronously this time. | |
188 host_resolver_->set_synchronous_mode(true); | |
189 EXPECT_EQ(ERR_CONNECTION_FAILED, | |
190 handle.Init("a", | |
191 params_, | |
192 kDefaultPriority, | |
193 callback.callback(), | |
194 &pool_, | |
195 BoundNetLog())); | |
196 } | |
197 | |
198 TEST_F(WebSocketTransportClientSocketPoolTest, PendingRequestsFinishFifo) { | |
199 // First request finishes asynchronously. | |
200 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
201 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
202 | |
203 // Make all subsequent host resolutions complete synchronously. | |
204 host_resolver_->set_synchronous_mode(true); | |
205 | |
206 // Rest of them wait for the first socket to be released. | |
207 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
208 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
209 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
210 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
211 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
212 | |
213 ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE); | |
214 | |
215 EXPECT_EQ(6, client_socket_factory_.allocation_count()); | |
216 | |
217 // One initial asynchronous request and then 5 pending requests. | |
218 EXPECT_EQ(6U, completion_count()); | |
219 | |
220 // The requests finish in FIFO order. | |
221 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
222 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
223 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
224 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
225 EXPECT_EQ(5, GetOrderOfRequest(5)); | |
226 EXPECT_EQ(6, GetOrderOfRequest(6)); | |
227 | |
228 // Make sure we test order of all requests made. | |
229 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(7)); | |
230 } | |
231 | |
232 TEST_F(WebSocketTransportClientSocketPoolTest, PendingRequests_NoKeepAlive) { | |
233 // First request finishes asynchronously. | |
234 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
235 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
236 | |
237 // Make all subsequent host resolutions complete synchronously. | |
238 host_resolver_->set_synchronous_mode(true); | |
239 | |
240 // Rest of them wait for the first socket to be released. | |
241 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
242 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
243 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
244 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
245 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
246 | |
247 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
248 | |
249 // The pending requests should finish successfully. | |
250 EXPECT_EQ(OK, request(1)->WaitForResult()); | |
251 EXPECT_EQ(OK, request(2)->WaitForResult()); | |
252 EXPECT_EQ(OK, request(3)->WaitForResult()); | |
253 EXPECT_EQ(OK, request(4)->WaitForResult()); | |
254 EXPECT_EQ(OK, request(5)->WaitForResult()); | |
255 | |
256 EXPECT_EQ(static_cast<int>(requests()->size()), | |
257 client_socket_factory_.allocation_count()); | |
258 | |
259 // First asynchronous request, and then last 5 pending requests. | |
260 EXPECT_EQ(6U, completion_count()); | |
261 } | |
262 | |
263 // This test will start up a RequestSocket() and then immediately Cancel() it. | |
264 // The pending host resolution will eventually complete, and destroy the | |
265 // ClientSocketPool which will crash if the group was not cleared properly. | |
266 TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequestClearGroup) { | |
267 TestCompletionCallback callback; | |
268 ClientSocketHandle handle; | |
269 EXPECT_EQ(ERR_IO_PENDING, | |
270 handle.Init("a", | |
271 params_, | |
272 kDefaultPriority, | |
273 callback.callback(), | |
274 &pool_, | |
275 BoundNetLog())); | |
276 handle.Reset(); | |
277 } | |
278 | |
279 TEST_F(WebSocketTransportClientSocketPoolTest, TwoRequestsCancelOne) { | |
280 ClientSocketHandle handle; | |
281 TestCompletionCallback callback; | |
282 ClientSocketHandle handle2; | |
283 TestCompletionCallback callback2; | |
284 | |
285 EXPECT_EQ(ERR_IO_PENDING, | |
286 handle.Init("a", | |
287 params_, | |
288 kDefaultPriority, | |
289 callback.callback(), | |
290 &pool_, | |
291 BoundNetLog())); | |
292 EXPECT_EQ(ERR_IO_PENDING, | |
293 handle2.Init("a", | |
294 params_, | |
295 kDefaultPriority, | |
296 callback2.callback(), | |
297 &pool_, | |
298 BoundNetLog())); | |
299 | |
300 handle.Reset(); | |
301 | |
302 EXPECT_EQ(OK, callback2.WaitForResult()); | |
303 handle2.Reset(); | |
304 } | |
305 | |
306 TEST_F(WebSocketTransportClientSocketPoolTest, ConnectCancelConnect) { | |
307 client_socket_factory_.set_default_client_socket_type( | |
308 MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET); | |
309 ClientSocketHandle handle; | |
310 TestCompletionCallback callback; | |
311 EXPECT_EQ(ERR_IO_PENDING, | |
312 handle.Init("a", | |
313 params_, | |
314 kDefaultPriority, | |
315 callback.callback(), | |
316 &pool_, | |
317 BoundNetLog())); | |
318 | |
319 handle.Reset(); | |
320 | |
321 TestCompletionCallback callback2; | |
322 EXPECT_EQ(ERR_IO_PENDING, | |
323 handle.Init("a", | |
324 params_, | |
325 kDefaultPriority, | |
326 callback2.callback(), | |
327 &pool_, | |
328 BoundNetLog())); | |
329 | |
330 host_resolver_->set_synchronous_mode(true); | |
331 // At this point, handle has two ConnectingSockets out for it. Due to the | |
332 // setting the mock resolver into synchronous mode, the host resolution for | |
333 // both will return in the same loop of the MessageLoop. The client socket | |
334 // is a pending socket, so the Connect() will asynchronously complete on the | |
335 // next loop of the MessageLoop. That means that the first | |
336 // ConnectingSocket will enter OnIOComplete, and then the second one will. | |
337 // If the first one is not cancelled, it will advance the load state, and | |
338 // then the second one will crash. | |
339 | |
340 EXPECT_EQ(OK, callback2.WaitForResult()); | |
341 EXPECT_FALSE(callback.have_result()); | |
342 | |
343 handle.Reset(); | |
344 } | |
345 | |
346 TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequest) { | |
347 // First request finishes asynchronously. | |
348 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
349 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
350 | |
351 // Make all subsequent host resolutions complete synchronously. | |
352 host_resolver_->set_synchronous_mode(true); | |
353 | |
354 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
355 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
356 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
357 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
358 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
359 | |
360 // Cancel a request. | |
361 const size_t index_to_cancel = 2; | |
362 EXPECT_FALSE(request(index_to_cancel)->handle()->is_initialized()); | |
363 request(index_to_cancel)->handle()->Reset(); | |
364 | |
365 ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE); | |
366 | |
367 EXPECT_EQ(5, client_socket_factory_.allocation_count()); | |
368 | |
369 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
370 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
371 EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, | |
372 GetOrderOfRequest(3)); // Canceled request. | |
373 EXPECT_EQ(3, GetOrderOfRequest(4)); | |
374 EXPECT_EQ(4, GetOrderOfRequest(5)); | |
375 EXPECT_EQ(5, GetOrderOfRequest(6)); | |
376 | |
377 // Make sure we test order of all requests made. | |
378 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(7)); | |
379 } | |
380 | |
381 class RequestSocketCallback : public TestCompletionCallbackBase { | |
382 public: | |
383 RequestSocketCallback(ClientSocketHandle* handle, | |
384 WebSocketTransportClientSocketPool* pool) | |
385 : handle_(handle), | |
386 pool_(pool), | |
387 within_callback_(false), | |
388 callback_(base::Bind(&RequestSocketCallback::OnComplete, | |
389 base::Unretained(this))) {} | |
390 | |
391 ~RequestSocketCallback() override {} | |
392 | |
393 const CompletionCallback& callback() const { return callback_; } | |
394 | |
395 private: | |
396 void OnComplete(int result) { | |
397 SetResult(result); | |
398 ASSERT_EQ(OK, result); | |
399 | |
400 if (!within_callback_) { | |
401 // Don't allow reuse of the socket. Disconnect it and then release it and | |
402 // run through the MessageLoop once to get it completely released. | |
403 handle_->socket()->Disconnect(); | |
404 handle_->Reset(); | |
405 { | |
406 base::MessageLoop::ScopedNestableTaskAllower allow( | |
407 base::MessageLoop::current()); | |
408 base::MessageLoop::current()->RunUntilIdle(); | |
409 } | |
410 within_callback_ = true; | |
411 scoped_refptr<TransportSocketParams> dest( | |
412 new TransportSocketParams( | |
413 HostPortPair("www.google.com", 80), | |
414 false, | |
415 false, | |
416 OnHostResolutionCallback(), | |
417 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); | |
418 int rv = | |
419 handle_->Init("a", dest, LOWEST, callback(), pool_, BoundNetLog()); | |
420 EXPECT_EQ(OK, rv); | |
421 } | |
422 } | |
423 | |
424 ClientSocketHandle* const handle_; | |
425 WebSocketTransportClientSocketPool* const pool_; | |
426 bool within_callback_; | |
427 CompletionCallback callback_; | |
428 | |
429 DISALLOW_COPY_AND_ASSIGN(RequestSocketCallback); | |
430 }; | |
431 | |
432 TEST_F(WebSocketTransportClientSocketPoolTest, RequestTwice) { | |
433 ClientSocketHandle handle; | |
434 RequestSocketCallback callback(&handle, &pool_); | |
435 scoped_refptr<TransportSocketParams> dest( | |
436 new TransportSocketParams( | |
437 HostPortPair("www.google.com", 80), | |
438 false, | |
439 false, | |
440 OnHostResolutionCallback(), | |
441 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); | |
442 int rv = handle.Init( | |
443 "a", dest, LOWEST, callback.callback(), &pool_, BoundNetLog()); | |
444 ASSERT_EQ(ERR_IO_PENDING, rv); | |
445 | |
446 // The callback is going to request "www.google.com". We want it to complete | |
447 // synchronously this time. | |
448 host_resolver_->set_synchronous_mode(true); | |
449 | |
450 EXPECT_EQ(OK, callback.WaitForResult()); | |
451 | |
452 handle.Reset(); | |
453 } | |
454 | |
455 // Make sure that pending requests get serviced after active requests get | |
456 // cancelled. | |
457 TEST_F(WebSocketTransportClientSocketPoolTest, | |
458 CancelActiveRequestWithPendingRequests) { | |
459 client_socket_factory_.set_default_client_socket_type( | |
460 MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET); | |
461 | |
462 // Queue up all the requests | |
463 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
464 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
465 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
466 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
467 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
468 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
469 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
470 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
471 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
472 | |
473 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. | |
474 ASSERT_LE(kMaxSocketsPerGroup, static_cast<int>(requests()->size())); | |
475 for (int i = 0; i < kMaxSocketsPerGroup; i++) | |
476 request(i)->handle()->Reset(); | |
477 | |
478 // Let's wait for the rest to complete now. | |
479 for (size_t i = kMaxSocketsPerGroup; i < requests()->size(); ++i) { | |
480 EXPECT_EQ(OK, request(i)->WaitForResult()); | |
481 request(i)->handle()->Reset(); | |
482 } | |
483 | |
484 EXPECT_EQ(requests()->size() - kMaxSocketsPerGroup, completion_count()); | |
485 } | |
486 | |
487 // Make sure that pending requests get serviced after active requests fail. | |
488 TEST_F(WebSocketTransportClientSocketPoolTest, | |
489 FailingActiveRequestWithPendingRequests) { | |
490 client_socket_factory_.set_default_client_socket_type( | |
491 MockTransportClientSocketFactory::MOCK_PENDING_FAILING_CLIENT_SOCKET); | |
492 | |
493 const int kNumRequests = 2 * kMaxSocketsPerGroup + 1; | |
494 ASSERT_LE(kNumRequests, kMaxSockets); // Otherwise the test will hang. | |
495 | |
496 // Queue up all the requests | |
497 for (int i = 0; i < kNumRequests; i++) | |
498 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
499 | |
500 for (int i = 0; i < kNumRequests; i++) | |
501 EXPECT_EQ(ERR_CONNECTION_FAILED, request(i)->WaitForResult()); | |
502 } | |
503 | |
504 // The lock on the endpoint is released when a ClientSocketHandle is reset. | |
505 TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleReset) { | |
506 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
507 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
508 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
509 EXPECT_FALSE(request(1)->handle()->is_initialized()); | |
510 request(0)->handle()->Reset(); | |
511 RunUntilIdle(); | |
512 EXPECT_TRUE(request(1)->handle()->is_initialized()); | |
513 } | |
514 | |
515 // The lock on the endpoint is released when a ClientSocketHandle is deleted. | |
516 TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleDelete) { | |
517 TestCompletionCallback callback; | |
518 scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle); | |
519 int rv = handle->Init( | |
520 "a", params_, LOW, callback.callback(), &pool_, BoundNetLog()); | |
521 EXPECT_EQ(ERR_IO_PENDING, rv); | |
522 | |
523 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
524 EXPECT_EQ(OK, callback.WaitForResult()); | |
525 EXPECT_FALSE(request(0)->handle()->is_initialized()); | |
526 handle.reset(); | |
527 RunUntilIdle(); | |
528 EXPECT_TRUE(request(0)->handle()->is_initialized()); | |
529 } | |
530 | |
531 // A new connection is performed when the lock on the previous connection is | |
532 // explicitly released. | |
533 TEST_F(WebSocketTransportClientSocketPoolTest, | |
534 ConnectionProceedsOnExplicitRelease) { | |
535 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
536 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
537 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
538 EXPECT_FALSE(request(1)->handle()->is_initialized()); | |
539 WebSocketTransportClientSocketPool::UnlockEndpoint(request(0)->handle()); | |
540 RunUntilIdle(); | |
541 EXPECT_TRUE(request(1)->handle()->is_initialized()); | |
542 } | |
543 | |
544 // A connection which is cancelled before completion does not block subsequent | |
545 // connections. | |
546 TEST_F(WebSocketTransportClientSocketPoolTest, | |
547 CancelDuringConnectionReleasesLock) { | |
548 MockTransportClientSocketFactory::ClientSocketType case_types[] = { | |
549 MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET, | |
550 MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET}; | |
551 | |
552 client_socket_factory_.set_client_socket_types(case_types, | |
553 arraysize(case_types)); | |
554 | |
555 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
556 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
557 RunUntilIdle(); | |
558 pool_.CancelRequest("a", request(0)->handle()); | |
559 EXPECT_EQ(OK, request(1)->WaitForResult()); | |
560 } | |
561 | |
562 // Test the case of the IPv6 address stalling, and falling back to the IPv4 | |
563 // socket which finishes first. | |
564 TEST_F(WebSocketTransportClientSocketPoolTest, | |
565 IPv6FallbackSocketIPv4FinishesFirst) { | |
566 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
567 kMaxSocketsPerGroup, | |
568 histograms_.get(), | |
569 host_resolver_.get(), | |
570 &client_socket_factory_, | |
571 NULL); | |
572 | |
573 MockTransportClientSocketFactory::ClientSocketType case_types[] = { | |
574 // This is the IPv6 socket. | |
575 MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET, | |
576 // This is the IPv4 socket. | |
577 MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET}; | |
578 | |
579 client_socket_factory_.set_client_socket_types(case_types, 2); | |
580 | |
581 // Resolve an AddressList with an IPv6 address first and then an IPv4 address. | |
582 host_resolver_->rules()->AddIPLiteralRule( | |
583 "*", "2:abcd::3:4:ff,2.2.2.2", std::string()); | |
584 | |
585 TestCompletionCallback callback; | |
586 ClientSocketHandle handle; | |
587 int rv = | |
588 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
589 EXPECT_EQ(ERR_IO_PENDING, rv); | |
590 EXPECT_FALSE(handle.is_initialized()); | |
591 EXPECT_FALSE(handle.socket()); | |
592 | |
593 EXPECT_EQ(OK, callback.WaitForResult()); | |
594 EXPECT_TRUE(handle.is_initialized()); | |
595 EXPECT_TRUE(handle.socket()); | |
596 IPEndPoint endpoint; | |
597 handle.socket()->GetLocalAddress(&endpoint); | |
598 EXPECT_EQ(kIPv4AddressSize, endpoint.address().size()); | |
599 EXPECT_EQ(2, client_socket_factory_.allocation_count()); | |
600 } | |
601 | |
602 // Test the case of the IPv6 address being slow, thus falling back to trying to | |
603 // connect to the IPv4 address, but having the connect to the IPv6 address | |
604 // finish first. | |
605 TEST_F(WebSocketTransportClientSocketPoolTest, | |
606 IPv6FallbackSocketIPv6FinishesFirst) { | |
607 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
608 kMaxSocketsPerGroup, | |
609 histograms_.get(), | |
610 host_resolver_.get(), | |
611 &client_socket_factory_, | |
612 NULL); | |
613 | |
614 MockTransportClientSocketFactory::ClientSocketType case_types[] = { | |
615 // This is the IPv6 socket. | |
616 MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET, | |
617 // This is the IPv4 socket. | |
618 MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET}; | |
619 | |
620 client_socket_factory_.set_client_socket_types(case_types, 2); | |
621 client_socket_factory_.set_delay(base::TimeDelta::FromMilliseconds( | |
622 TransportConnectJobHelper::kIPv6FallbackTimerInMs + 50)); | |
623 | |
624 // Resolve an AddressList with an IPv6 address first and then an IPv4 address. | |
625 host_resolver_->rules()->AddIPLiteralRule( | |
626 "*", "2:abcd::3:4:ff,2.2.2.2", std::string()); | |
627 | |
628 TestCompletionCallback callback; | |
629 ClientSocketHandle handle; | |
630 int rv = | |
631 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
632 EXPECT_EQ(ERR_IO_PENDING, rv); | |
633 EXPECT_FALSE(handle.is_initialized()); | |
634 EXPECT_FALSE(handle.socket()); | |
635 | |
636 EXPECT_EQ(OK, callback.WaitForResult()); | |
637 EXPECT_TRUE(handle.is_initialized()); | |
638 EXPECT_TRUE(handle.socket()); | |
639 IPEndPoint endpoint; | |
640 handle.socket()->GetLocalAddress(&endpoint); | |
641 EXPECT_EQ(kIPv6AddressSize, endpoint.address().size()); | |
642 EXPECT_EQ(2, client_socket_factory_.allocation_count()); | |
643 } | |
644 | |
645 TEST_F(WebSocketTransportClientSocketPoolTest, | |
646 IPv6NoIPv4AddressesToFallbackTo) { | |
647 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
648 kMaxSocketsPerGroup, | |
649 histograms_.get(), | |
650 host_resolver_.get(), | |
651 &client_socket_factory_, | |
652 NULL); | |
653 | |
654 client_socket_factory_.set_default_client_socket_type( | |
655 MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET); | |
656 | |
657 // Resolve an AddressList with only IPv6 addresses. | |
658 host_resolver_->rules()->AddIPLiteralRule( | |
659 "*", "2:abcd::3:4:ff,3:abcd::3:4:ff", std::string()); | |
660 | |
661 TestCompletionCallback callback; | |
662 ClientSocketHandle handle; | |
663 int rv = | |
664 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
665 EXPECT_EQ(ERR_IO_PENDING, rv); | |
666 EXPECT_FALSE(handle.is_initialized()); | |
667 EXPECT_FALSE(handle.socket()); | |
668 | |
669 EXPECT_EQ(OK, callback.WaitForResult()); | |
670 EXPECT_TRUE(handle.is_initialized()); | |
671 EXPECT_TRUE(handle.socket()); | |
672 IPEndPoint endpoint; | |
673 handle.socket()->GetLocalAddress(&endpoint); | |
674 EXPECT_EQ(kIPv6AddressSize, endpoint.address().size()); | |
675 EXPECT_EQ(1, client_socket_factory_.allocation_count()); | |
676 } | |
677 | |
678 TEST_F(WebSocketTransportClientSocketPoolTest, IPv4HasNoFallback) { | |
679 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
680 kMaxSocketsPerGroup, | |
681 histograms_.get(), | |
682 host_resolver_.get(), | |
683 &client_socket_factory_, | |
684 NULL); | |
685 | |
686 client_socket_factory_.set_default_client_socket_type( | |
687 MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET); | |
688 | |
689 // Resolve an AddressList with only IPv4 addresses. | |
690 host_resolver_->rules()->AddIPLiteralRule("*", "1.1.1.1", std::string()); | |
691 | |
692 TestCompletionCallback callback; | |
693 ClientSocketHandle handle; | |
694 int rv = | |
695 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
696 EXPECT_EQ(ERR_IO_PENDING, rv); | |
697 EXPECT_FALSE(handle.is_initialized()); | |
698 EXPECT_FALSE(handle.socket()); | |
699 | |
700 EXPECT_EQ(OK, callback.WaitForResult()); | |
701 EXPECT_TRUE(handle.is_initialized()); | |
702 EXPECT_TRUE(handle.socket()); | |
703 IPEndPoint endpoint; | |
704 handle.socket()->GetLocalAddress(&endpoint); | |
705 EXPECT_EQ(kIPv4AddressSize, endpoint.address().size()); | |
706 EXPECT_EQ(1, client_socket_factory_.allocation_count()); | |
707 } | |
708 | |
709 // If all IPv6 addresses fail to connect synchronously, then IPv4 connections | |
710 // proceeed immediately. | |
711 TEST_F(WebSocketTransportClientSocketPoolTest, IPv6InstantFail) { | |
712 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
713 kMaxSocketsPerGroup, | |
714 histograms_.get(), | |
715 host_resolver_.get(), | |
716 &client_socket_factory_, | |
717 NULL); | |
718 | |
719 MockTransportClientSocketFactory::ClientSocketType case_types[] = { | |
720 // First IPv6 socket. | |
721 MockTransportClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET, | |
722 // Second IPv6 socket. | |
723 MockTransportClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET, | |
724 // This is the IPv4 socket. | |
725 MockTransportClientSocketFactory::MOCK_CLIENT_SOCKET}; | |
726 | |
727 client_socket_factory_.set_client_socket_types(case_types, | |
728 arraysize(case_types)); | |
729 | |
730 // Resolve an AddressList with two IPv6 addresses and then an IPv4 address. | |
731 host_resolver_->rules()->AddIPLiteralRule( | |
732 "*", "2:abcd::3:4:ff,2:abcd::3:5:ff,2.2.2.2", std::string()); | |
733 host_resolver_->set_synchronous_mode(true); | |
734 TestCompletionCallback callback; | |
735 ClientSocketHandle handle; | |
736 int rv = | |
737 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
738 EXPECT_EQ(OK, rv); | |
739 ASSERT_TRUE(handle.socket()); | |
740 | |
741 IPEndPoint endpoint; | |
742 handle.socket()->GetPeerAddress(&endpoint); | |
743 EXPECT_EQ("2.2.2.2", endpoint.ToStringWithoutPort()); | |
744 } | |
745 | |
746 // If all IPv6 addresses fail before the IPv4 fallback timeout, then the IPv4 | |
747 // connections proceed immediately. | |
748 TEST_F(WebSocketTransportClientSocketPoolTest, IPv6RapidFail) { | |
749 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
750 kMaxSocketsPerGroup, | |
751 histograms_.get(), | |
752 host_resolver_.get(), | |
753 &client_socket_factory_, | |
754 NULL); | |
755 | |
756 MockTransportClientSocketFactory::ClientSocketType case_types[] = { | |
757 // First IPv6 socket. | |
758 MockTransportClientSocketFactory::MOCK_PENDING_FAILING_CLIENT_SOCKET, | |
759 // Second IPv6 socket. | |
760 MockTransportClientSocketFactory::MOCK_PENDING_FAILING_CLIENT_SOCKET, | |
761 // This is the IPv4 socket. | |
762 MockTransportClientSocketFactory::MOCK_CLIENT_SOCKET}; | |
763 | |
764 client_socket_factory_.set_client_socket_types(case_types, | |
765 arraysize(case_types)); | |
766 | |
767 // Resolve an AddressList with two IPv6 addresses and then an IPv4 address. | |
768 host_resolver_->rules()->AddIPLiteralRule( | |
769 "*", "2:abcd::3:4:ff,2:abcd::3:5:ff,2.2.2.2", std::string()); | |
770 | |
771 TestCompletionCallback callback; | |
772 ClientSocketHandle handle; | |
773 int rv = | |
774 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
775 EXPECT_EQ(ERR_IO_PENDING, rv); | |
776 EXPECT_FALSE(handle.socket()); | |
777 | |
778 base::Time start(base::Time::NowFromSystemTime()); | |
779 EXPECT_EQ(OK, callback.WaitForResult()); | |
780 EXPECT_LT(base::Time::NowFromSystemTime() - start, | |
781 base::TimeDelta::FromMilliseconds( | |
782 TransportConnectJobHelper::kIPv6FallbackTimerInMs)); | |
783 ASSERT_TRUE(handle.socket()); | |
784 | |
785 IPEndPoint endpoint; | |
786 handle.socket()->GetPeerAddress(&endpoint); | |
787 EXPECT_EQ("2.2.2.2", endpoint.ToStringWithoutPort()); | |
788 } | |
789 | |
790 // If two sockets connect successfully, the one which connected first wins (this | |
791 // can only happen if the sockets are different types, since sockets of the same | |
792 // type do not race). | |
793 TEST_F(WebSocketTransportClientSocketPoolTest, FirstSuccessWins) { | |
794 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
795 kMaxSocketsPerGroup, | |
796 histograms_.get(), | |
797 host_resolver_.get(), | |
798 &client_socket_factory_, | |
799 NULL); | |
800 | |
801 client_socket_factory_.set_default_client_socket_type( | |
802 MockTransportClientSocketFactory::MOCK_TRIGGERABLE_CLIENT_SOCKET); | |
803 | |
804 // Resolve an AddressList with an IPv6 addresses and an IPv4 address. | |
805 host_resolver_->rules()->AddIPLiteralRule( | |
806 "*", "2:abcd::3:4:ff,2.2.2.2", std::string()); | |
807 | |
808 TestCompletionCallback callback; | |
809 ClientSocketHandle handle; | |
810 int rv = | |
811 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
812 EXPECT_EQ(ERR_IO_PENDING, rv); | |
813 ASSERT_FALSE(handle.socket()); | |
814 | |
815 base::Closure ipv6_connect_trigger = | |
816 client_socket_factory_.WaitForTriggerableSocketCreation(); | |
817 base::Closure ipv4_connect_trigger = | |
818 client_socket_factory_.WaitForTriggerableSocketCreation(); | |
819 | |
820 ipv4_connect_trigger.Run(); | |
821 ipv6_connect_trigger.Run(); | |
822 | |
823 EXPECT_EQ(OK, callback.WaitForResult()); | |
824 ASSERT_TRUE(handle.socket()); | |
825 | |
826 IPEndPoint endpoint; | |
827 handle.socket()->GetPeerAddress(&endpoint); | |
828 EXPECT_EQ("2.2.2.2", endpoint.ToStringWithoutPort()); | |
829 } | |
830 | |
831 // We should not report failure until all connections have failed. | |
832 TEST_F(WebSocketTransportClientSocketPoolTest, LastFailureWins) { | |
833 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
834 kMaxSocketsPerGroup, | |
835 histograms_.get(), | |
836 host_resolver_.get(), | |
837 &client_socket_factory_, | |
838 NULL); | |
839 | |
840 client_socket_factory_.set_default_client_socket_type( | |
841 MockTransportClientSocketFactory::MOCK_DELAYED_FAILING_CLIENT_SOCKET); | |
842 base::TimeDelta delay = base::TimeDelta::FromMilliseconds( | |
843 TransportConnectJobHelper::kIPv6FallbackTimerInMs / 3); | |
844 client_socket_factory_.set_delay(delay); | |
845 | |
846 // Resolve an AddressList with 4 IPv6 addresses and 2 IPv4 addresses. | |
847 host_resolver_->rules()->AddIPLiteralRule("*", | |
848 "1:abcd::3:4:ff,2:abcd::3:4:ff," | |
849 "3:abcd::3:4:ff,4:abcd::3:4:ff," | |
850 "1.1.1.1,2.2.2.2", | |
851 std::string()); | |
852 | |
853 // Expected order of events: | |
854 // After 100ms: Connect to 1:abcd::3:4:ff times out | |
855 // After 200ms: Connect to 2:abcd::3:4:ff times out | |
856 // After 300ms: Connect to 3:abcd::3:4:ff times out, IPv4 fallback starts | |
857 // After 400ms: Connect to 4:abcd::3:4:ff and 1.1.1.1 time out | |
858 // After 500ms: Connect to 2.2.2.2 times out | |
859 | |
860 TestCompletionCallback callback; | |
861 ClientSocketHandle handle; | |
862 base::Time start(base::Time::NowFromSystemTime()); | |
863 int rv = | |
864 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
865 EXPECT_EQ(ERR_IO_PENDING, rv); | |
866 | |
867 EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
868 | |
869 EXPECT_GE(base::Time::NowFromSystemTime() - start, delay * 5); | |
870 } | |
871 | |
872 // Global timeout for all connects applies. This test is disabled by default | |
873 // because it takes 4 minutes. Run with --gtest_also_run_disabled_tests if you | |
874 // want to run it. | |
875 TEST_F(WebSocketTransportClientSocketPoolTest, DISABLED_OverallTimeoutApplies) { | |
876 WebSocketTransportClientSocketPool pool(kMaxSockets, | |
877 kMaxSocketsPerGroup, | |
878 histograms_.get(), | |
879 host_resolver_.get(), | |
880 &client_socket_factory_, | |
881 NULL); | |
882 const base::TimeDelta connect_job_timeout = pool.ConnectionTimeout(); | |
883 | |
884 client_socket_factory_.set_default_client_socket_type( | |
885 MockTransportClientSocketFactory::MOCK_DELAYED_FAILING_CLIENT_SOCKET); | |
886 client_socket_factory_.set_delay(base::TimeDelta::FromSeconds(1) + | |
887 connect_job_timeout / 6); | |
888 | |
889 // Resolve an AddressList with 6 IPv6 addresses and 6 IPv4 addresses. | |
890 host_resolver_->rules()->AddIPLiteralRule("*", | |
891 "1:abcd::3:4:ff,2:abcd::3:4:ff," | |
892 "3:abcd::3:4:ff,4:abcd::3:4:ff," | |
893 "5:abcd::3:4:ff,6:abcd::3:4:ff," | |
894 "1.1.1.1,2.2.2.2,3.3.3.3," | |
895 "4.4.4.4,5.5.5.5,6.6.6.6", | |
896 std::string()); | |
897 | |
898 TestCompletionCallback callback; | |
899 ClientSocketHandle handle; | |
900 | |
901 int rv = | |
902 handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog()); | |
903 EXPECT_EQ(ERR_IO_PENDING, rv); | |
904 | |
905 EXPECT_EQ(ERR_TIMED_OUT, callback.WaitForResult()); | |
906 } | |
907 | |
908 TEST_F(WebSocketTransportClientSocketPoolTest, MaxSocketsEnforced) { | |
909 host_resolver_->set_synchronous_mode(true); | |
910 for (int i = 0; i < kMaxSockets; ++i) { | |
911 ASSERT_EQ(OK, StartRequest("a", kDefaultPriority)); | |
912 WebSocketTransportClientSocketPool::UnlockEndpoint(request(i)->handle()); | |
913 RunUntilIdle(); | |
914 } | |
915 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
916 } | |
917 | |
918 TEST_F(WebSocketTransportClientSocketPoolTest, MaxSocketsEnforcedWhenPending) { | |
919 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
920 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
921 } | |
922 // Now there are 32 sockets waiting to connect, and one stalled. | |
923 for (int i = 0; i < kMaxSockets; ++i) { | |
924 RunUntilIdle(); | |
925 EXPECT_TRUE(request(i)->handle()->is_initialized()); | |
926 EXPECT_TRUE(request(i)->handle()->socket()); | |
927 WebSocketTransportClientSocketPool::UnlockEndpoint(request(i)->handle()); | |
928 } | |
929 // Now there are 32 sockets connected, and one stalled. | |
930 RunUntilIdle(); | |
931 EXPECT_FALSE(request(kMaxSockets)->handle()->is_initialized()); | |
932 EXPECT_FALSE(request(kMaxSockets)->handle()->socket()); | |
933 } | |
934 | |
935 TEST_F(WebSocketTransportClientSocketPoolTest, StalledSocketReleased) { | |
936 host_resolver_->set_synchronous_mode(true); | |
937 for (int i = 0; i < kMaxSockets; ++i) { | |
938 ASSERT_EQ(OK, StartRequest("a", kDefaultPriority)); | |
939 WebSocketTransportClientSocketPool::UnlockEndpoint(request(i)->handle()); | |
940 RunUntilIdle(); | |
941 } | |
942 | |
943 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
944 ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
945 EXPECT_TRUE(request(kMaxSockets)->handle()->is_initialized()); | |
946 EXPECT_TRUE(request(kMaxSockets)->handle()->socket()); | |
947 } | |
948 | |
949 TEST_F(WebSocketTransportClientSocketPoolTest, IsStalledTrueWhenStalled) { | |
950 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
951 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
952 } | |
953 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
954 EXPECT_TRUE(pool_.IsStalled()); | |
955 } | |
956 | |
957 TEST_F(WebSocketTransportClientSocketPoolTest, | |
958 CancellingPendingSocketUnstallsStalledSocket) { | |
959 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
960 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
961 } | |
962 EXPECT_EQ(OK, request(0)->WaitForResult()); | |
963 request(1)->handle()->Reset(); | |
964 RunUntilIdle(); | |
965 EXPECT_FALSE(pool_.IsStalled()); | |
966 } | |
967 | |
968 TEST_F(WebSocketTransportClientSocketPoolTest, | |
969 LoadStateOfStalledSocketIsWaitingForAvailableSocket) { | |
970 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
971 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
972 } | |
973 EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, | |
974 pool_.GetLoadState("a", request(kMaxSockets)->handle())); | |
975 } | |
976 | |
977 TEST_F(WebSocketTransportClientSocketPoolTest, | |
978 CancellingStalledSocketUnstallsPool) { | |
979 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
980 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
981 } | |
982 request(kMaxSockets)->handle()->Reset(); | |
983 RunUntilIdle(); | |
984 EXPECT_FALSE(pool_.IsStalled()); | |
985 } | |
986 | |
987 TEST_F(WebSocketTransportClientSocketPoolTest, | |
988 FlushWithErrorFlushesPendingConnections) { | |
989 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
990 pool_.FlushWithError(ERR_FAILED); | |
991 EXPECT_EQ(ERR_FAILED, request(0)->WaitForResult()); | |
992 } | |
993 | |
994 TEST_F(WebSocketTransportClientSocketPoolTest, | |
995 FlushWithErrorFlushesStalledConnections) { | |
996 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
997 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
998 } | |
999 pool_.FlushWithError(ERR_FAILED); | |
1000 EXPECT_EQ(ERR_FAILED, request(kMaxSockets)->WaitForResult()); | |
1001 } | |
1002 | |
1003 TEST_F(WebSocketTransportClientSocketPoolTest, | |
1004 AfterFlushWithErrorCanMakeNewConnections) { | |
1005 for (int i = 0; i < kMaxSockets + 1; ++i) { | |
1006 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1007 } | |
1008 pool_.FlushWithError(ERR_FAILED); | |
1009 host_resolver_->set_synchronous_mode(true); | |
1010 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); | |
1011 } | |
1012 | |
1013 // Deleting pending connections can release the lock on the endpoint, which can | |
1014 // in principle lead to other pending connections succeeding. However, when we | |
1015 // call FlushWithError(), everything should fail. | |
1016 TEST_F(WebSocketTransportClientSocketPoolTest, | |
1017 FlushWithErrorDoesNotCauseSuccessfulConnections) { | |
1018 host_resolver_->set_synchronous_mode(true); | |
1019 MockTransportClientSocketFactory::ClientSocketType first_type[] = { | |
1020 // First socket | |
1021 MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET | |
1022 }; | |
1023 client_socket_factory_.set_client_socket_types(first_type, | |
1024 arraysize(first_type)); | |
1025 // The rest of the sockets will connect synchronously. | |
1026 client_socket_factory_.set_default_client_socket_type( | |
1027 MockTransportClientSocketFactory::MOCK_CLIENT_SOCKET); | |
1028 for (int i = 0; i < kMaxSockets; ++i) { | |
1029 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1030 } | |
1031 // Now we have one socket in STATE_TRANSPORT_CONNECT and the rest in | |
1032 // STATE_OBTAIN_LOCK. If any of the sockets in STATE_OBTAIN_LOCK is given the | |
1033 // lock, they will synchronously connect. | |
1034 pool_.FlushWithError(ERR_FAILED); | |
1035 for (int i = 0; i < kMaxSockets; ++i) { | |
1036 EXPECT_EQ(ERR_FAILED, request(i)->WaitForResult()); | |
1037 } | |
1038 } | |
1039 | |
1040 // This is a regression test for the first attempted fix for | |
1041 // FlushWithErrorDoesNotCauseSuccessfulConnections. Because a ConnectJob can | |
1042 // have both IPv4 and IPv6 subjobs, it can be both connecting and waiting for | |
1043 // the lock at the same time. | |
1044 TEST_F(WebSocketTransportClientSocketPoolTest, | |
1045 FlushWithErrorDoesNotCauseSuccessfulConnectionsMultipleAddressTypes) { | |
1046 host_resolver_->set_synchronous_mode(true); | |
1047 // The first |kMaxSockets| sockets to connect will be IPv6. Then we will have | |
1048 // one IPv4. | |
1049 std::vector<MockTransportClientSocketFactory::ClientSocketType> socket_types( | |
1050 kMaxSockets + 1, | |
1051 MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET); | |
1052 client_socket_factory_.set_client_socket_types(&socket_types[0], | |
1053 socket_types.size()); | |
1054 // The rest of the sockets will connect synchronously. | |
1055 client_socket_factory_.set_default_client_socket_type( | |
1056 MockTransportClientSocketFactory::MOCK_CLIENT_SOCKET); | |
1057 for (int i = 0; i < kMaxSockets; ++i) { | |
1058 host_resolver_->rules()->ClearRules(); | |
1059 // Each connect job has a different IPv6 address but the same IPv4 address. | |
1060 // So the IPv6 connections happen in parallel but the IPv4 ones are | |
1061 // serialised. | |
1062 host_resolver_->rules()->AddIPLiteralRule("*", | |
1063 base::StringPrintf( | |
1064 "%x:abcd::3:4:ff," | |
1065 "1.1.1.1", | |
1066 i + 1), | |
1067 std::string()); | |
1068 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1069 } | |
1070 // Now we have |kMaxSockets| IPv6 sockets stalled in connect. No IPv4 sockets | |
1071 // are started yet. | |
1072 RunLoopForTimePeriod(base::TimeDelta::FromMilliseconds( | |
1073 TransportConnectJobHelper::kIPv6FallbackTimerInMs)); | |
1074 // Now we have |kMaxSockets| IPv6 sockets and one IPv4 socket stalled in | |
1075 // connect, and |kMaxSockets - 1| IPv4 sockets waiting for the endpoint lock. | |
1076 pool_.FlushWithError(ERR_FAILED); | |
1077 for (int i = 0; i < kMaxSockets; ++i) { | |
1078 EXPECT_EQ(ERR_FAILED, request(i)->WaitForResult()); | |
1079 } | |
1080 } | |
1081 | |
1082 // Sockets that have had ownership transferred to a ClientSocketHandle should | |
1083 // not be affected by FlushWithError. | |
1084 TEST_F(WebSocketTransportClientSocketPoolTest, | |
1085 FlushWithErrorDoesNotAffectHandedOutSockets) { | |
1086 host_resolver_->set_synchronous_mode(true); | |
1087 MockTransportClientSocketFactory::ClientSocketType socket_types[] = { | |
1088 MockTransportClientSocketFactory::MOCK_CLIENT_SOCKET, | |
1089 MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET}; | |
1090 client_socket_factory_.set_client_socket_types(socket_types, | |
1091 arraysize(socket_types)); | |
1092 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); | |
1093 // Socket has been "handed out". | |
1094 EXPECT_TRUE(request(0)->handle()->socket()); | |
1095 | |
1096 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1097 // Now we have one socket handed out, and one pending. | |
1098 pool_.FlushWithError(ERR_FAILED); | |
1099 EXPECT_EQ(ERR_FAILED, request(1)->WaitForResult()); | |
1100 // Socket owned by ClientSocketHandle is unaffected: | |
1101 EXPECT_TRUE(request(0)->handle()->socket()); | |
1102 // Return it to the pool (which deletes it). | |
1103 request(0)->handle()->Reset(); | |
1104 } | |
1105 | |
1106 // Sockets should not be leaked if CancelRequest() is called in between | |
1107 // SetSocket() being called on the ClientSocketHandle and InvokeUserCallback(). | |
1108 TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequestReclaimsSockets) { | |
1109 host_resolver_->set_synchronous_mode(true); | |
1110 MockTransportClientSocketFactory::ClientSocketType socket_types[] = { | |
1111 MockTransportClientSocketFactory::MOCK_TRIGGERABLE_CLIENT_SOCKET, | |
1112 MockTransportClientSocketFactory::MOCK_CLIENT_SOCKET}; | |
1113 | |
1114 client_socket_factory_.set_client_socket_types(socket_types, | |
1115 arraysize(socket_types)); | |
1116 | |
1117 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1118 | |
1119 base::Closure connect_trigger = | |
1120 client_socket_factory_.WaitForTriggerableSocketCreation(); | |
1121 | |
1122 connect_trigger.Run(); // Calls InvokeUserCallbackLater() | |
1123 | |
1124 request(0)->handle()->Reset(); // calls CancelRequest() | |
1125 | |
1126 RunUntilIdle(); | |
1127 // We should now be able to create a new connection without blocking on the | |
1128 // endpoint lock. | |
1129 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); | |
1130 } | |
1131 | |
1132 // A handshake completing and then the WebSocket closing should only release one | |
1133 // Endpoint, not two. | |
1134 TEST_F(WebSocketTransportClientSocketPoolTest, EndpointLockIsOnlyReleasedOnce) { | |
1135 host_resolver_->set_synchronous_mode(true); | |
1136 ASSERT_EQ(OK, StartRequest("a", kDefaultPriority)); | |
1137 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1138 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | |
1139 // First socket completes handshake. | |
1140 WebSocketTransportClientSocketPool::UnlockEndpoint(request(0)->handle()); | |
1141 RunUntilIdle(); | |
1142 // First socket is closed. | |
1143 request(0)->handle()->Reset(); | |
1144 // Second socket should have been released. | |
1145 EXPECT_EQ(OK, request(1)->WaitForResult()); | |
1146 // Third socket should still be waiting for endpoint. | |
1147 ASSERT_FALSE(request(2)->handle()->is_initialized()); | |
1148 EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, | |
1149 request(2)->handle()->GetLoadState()); | |
1150 } | |
1151 | |
1152 } // namespace | |
1153 | |
1154 } // namespace net | |
OLD | NEW |