OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/client_socket_pool_base.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/bind_helpers.h" | |
11 #include "base/callback.h" | |
12 #include "base/memory/ref_counted.h" | |
13 #include "base/memory/scoped_vector.h" | |
14 #include "base/memory/weak_ptr.h" | |
15 #include "base/message_loop/message_loop.h" | |
16 #include "base/run_loop.h" | |
17 #include "base/strings/string_number_conversions.h" | |
18 #include "base/strings/stringprintf.h" | |
19 #include "base/threading/platform_thread.h" | |
20 #include "base/values.h" | |
21 #include "net/base/load_timing_info.h" | |
22 #include "net/base/load_timing_info_test_util.h" | |
23 #include "net/base/net_errors.h" | |
24 #include "net/base/net_log.h" | |
25 #include "net/base/net_log_unittest.h" | |
26 #include "net/base/request_priority.h" | |
27 #include "net/base/test_completion_callback.h" | |
28 #include "net/http/http_response_headers.h" | |
29 #include "net/socket/client_socket_factory.h" | |
30 #include "net/socket/client_socket_handle.h" | |
31 #include "net/socket/client_socket_pool_histograms.h" | |
32 #include "net/socket/socket_test_util.h" | |
33 #include "net/socket/ssl_client_socket.h" | |
34 #include "net/socket/stream_socket.h" | |
35 #include "net/udp/datagram_client_socket.h" | |
36 #include "testing/gmock/include/gmock/gmock.h" | |
37 #include "testing/gtest/include/gtest/gtest.h" | |
38 | |
39 using ::testing::Invoke; | |
40 using ::testing::Return; | |
41 | |
42 namespace net { | |
43 | |
44 namespace { | |
45 | |
46 const int kDefaultMaxSockets = 4; | |
47 const int kDefaultMaxSocketsPerGroup = 2; | |
48 | |
49 // Make sure |handle| sets load times correctly when it has been assigned a | |
50 // reused socket. | |
51 void TestLoadTimingInfoConnectedReused(const ClientSocketHandle& handle) { | |
52 LoadTimingInfo load_timing_info; | |
53 // Only pass true in as |is_reused|, as in general, HttpStream types should | |
54 // have stricter concepts of reuse than socket pools. | |
55 EXPECT_TRUE(handle.GetLoadTimingInfo(true, &load_timing_info)); | |
56 | |
57 EXPECT_EQ(true, load_timing_info.socket_reused); | |
58 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
59 | |
60 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); | |
61 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
62 } | |
63 | |
64 // Make sure |handle| sets load times correctly when it has been assigned a | |
65 // fresh socket. Also runs TestLoadTimingInfoConnectedReused, since the owner | |
66 // of a connection where |is_reused| is false may consider the connection | |
67 // reused. | |
68 void TestLoadTimingInfoConnectedNotReused(const ClientSocketHandle& handle) { | |
69 EXPECT_FALSE(handle.is_reused()); | |
70 | |
71 LoadTimingInfo load_timing_info; | |
72 EXPECT_TRUE(handle.GetLoadTimingInfo(false, &load_timing_info)); | |
73 | |
74 EXPECT_FALSE(load_timing_info.socket_reused); | |
75 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
76 | |
77 ExpectConnectTimingHasTimes(load_timing_info.connect_timing, | |
78 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); | |
79 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
80 | |
81 TestLoadTimingInfoConnectedReused(handle); | |
82 } | |
83 | |
84 // Make sure |handle| sets load times correctly, in the case that it does not | |
85 // currently have a socket. | |
86 void TestLoadTimingInfoNotConnected(const ClientSocketHandle& handle) { | |
87 // Should only be set to true once a socket is assigned, if at all. | |
88 EXPECT_FALSE(handle.is_reused()); | |
89 | |
90 LoadTimingInfo load_timing_info; | |
91 EXPECT_FALSE(handle.GetLoadTimingInfo(false, &load_timing_info)); | |
92 | |
93 EXPECT_FALSE(load_timing_info.socket_reused); | |
94 EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); | |
95 | |
96 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); | |
97 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); | |
98 } | |
99 | |
100 class TestSocketParams : public base::RefCounted<TestSocketParams> { | |
101 public: | |
102 explicit TestSocketParams(bool ignore_limits) | |
103 : ignore_limits_(ignore_limits) {} | |
104 | |
105 bool ignore_limits() { return ignore_limits_; } | |
106 | |
107 private: | |
108 friend class base::RefCounted<TestSocketParams>; | |
109 ~TestSocketParams() {} | |
110 | |
111 const bool ignore_limits_; | |
112 }; | |
113 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; | |
114 | |
115 class MockClientSocket : public StreamSocket { | |
116 public: | |
117 explicit MockClientSocket(net::NetLog* net_log) | |
118 : connected_(false), | |
119 has_unread_data_(false), | |
120 net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), | |
121 was_used_to_convey_data_(false) { | |
122 } | |
123 | |
124 // Sets whether the socket has unread data. If true, the next call to Read() | |
125 // will return 1 byte and IsConnectedAndIdle() will return false. | |
126 void set_has_unread_data(bool has_unread_data) { | |
127 has_unread_data_ = has_unread_data; | |
128 } | |
129 | |
130 // Socket implementation. | |
131 int Read(IOBuffer* /* buf */, | |
132 int len, | |
133 const CompletionCallback& /* callback */) override { | |
134 if (has_unread_data_ && len > 0) { | |
135 has_unread_data_ = false; | |
136 was_used_to_convey_data_ = true; | |
137 return 1; | |
138 } | |
139 return ERR_UNEXPECTED; | |
140 } | |
141 | |
142 int Write(IOBuffer* /* buf */, | |
143 int len, | |
144 const CompletionCallback& /* callback */) override { | |
145 was_used_to_convey_data_ = true; | |
146 return len; | |
147 } | |
148 int SetReceiveBufferSize(int32 size) override { return OK; } | |
149 int SetSendBufferSize(int32 size) override { return OK; } | |
150 | |
151 // StreamSocket implementation. | |
152 int Connect(const CompletionCallback& callback) override { | |
153 connected_ = true; | |
154 return OK; | |
155 } | |
156 | |
157 void Disconnect() override { connected_ = false; } | |
158 bool IsConnected() const override { return connected_; } | |
159 bool IsConnectedAndIdle() const override { | |
160 return connected_ && !has_unread_data_; | |
161 } | |
162 | |
163 int GetPeerAddress(IPEndPoint* /* address */) const override { | |
164 return ERR_UNEXPECTED; | |
165 } | |
166 | |
167 int GetLocalAddress(IPEndPoint* /* address */) const override { | |
168 return ERR_UNEXPECTED; | |
169 } | |
170 | |
171 const BoundNetLog& NetLog() const override { return net_log_; } | |
172 | |
173 void SetSubresourceSpeculation() override {} | |
174 void SetOmniboxSpeculation() override {} | |
175 bool WasEverUsed() const override { return was_used_to_convey_data_; } | |
176 bool UsingTCPFastOpen() const override { return false; } | |
177 bool WasNpnNegotiated() const override { return false; } | |
178 NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; } | |
179 bool GetSSLInfo(SSLInfo* ssl_info) override { return false; } | |
180 | |
181 private: | |
182 bool connected_; | |
183 bool has_unread_data_; | |
184 BoundNetLog net_log_; | |
185 bool was_used_to_convey_data_; | |
186 | |
187 DISALLOW_COPY_AND_ASSIGN(MockClientSocket); | |
188 }; | |
189 | |
190 class TestConnectJob; | |
191 | |
192 class MockClientSocketFactory : public ClientSocketFactory { | |
193 public: | |
194 MockClientSocketFactory() : allocation_count_(0) {} | |
195 | |
196 scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket( | |
197 DatagramSocket::BindType bind_type, | |
198 const RandIntCallback& rand_int_cb, | |
199 NetLog* net_log, | |
200 const NetLog::Source& source) override { | |
201 NOTREACHED(); | |
202 return scoped_ptr<DatagramClientSocket>(); | |
203 } | |
204 | |
205 scoped_ptr<StreamSocket> CreateTransportClientSocket( | |
206 const AddressList& addresses, | |
207 NetLog* /* net_log */, | |
208 const NetLog::Source& /*source*/) override { | |
209 allocation_count_++; | |
210 return scoped_ptr<StreamSocket>(); | |
211 } | |
212 | |
213 scoped_ptr<SSLClientSocket> CreateSSLClientSocket( | |
214 scoped_ptr<ClientSocketHandle> transport_socket, | |
215 const HostPortPair& host_and_port, | |
216 const SSLConfig& ssl_config, | |
217 const SSLClientSocketContext& context) override { | |
218 NOTIMPLEMENTED(); | |
219 return scoped_ptr<SSLClientSocket>(); | |
220 } | |
221 | |
222 void ClearSSLSessionCache() override { NOTIMPLEMENTED(); } | |
223 | |
224 void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); } | |
225 | |
226 void SignalJobs(); | |
227 | |
228 void SignalJob(size_t job); | |
229 | |
230 void SetJobLoadState(size_t job, LoadState load_state); | |
231 | |
232 int allocation_count() const { return allocation_count_; } | |
233 | |
234 private: | |
235 int allocation_count_; | |
236 std::vector<TestConnectJob*> waiting_jobs_; | |
237 }; | |
238 | |
239 class TestConnectJob : public ConnectJob { | |
240 public: | |
241 enum JobType { | |
242 kMockJob, | |
243 kMockFailingJob, | |
244 kMockPendingJob, | |
245 kMockPendingFailingJob, | |
246 kMockWaitingJob, | |
247 kMockRecoverableJob, | |
248 kMockPendingRecoverableJob, | |
249 kMockAdditionalErrorStateJob, | |
250 kMockPendingAdditionalErrorStateJob, | |
251 kMockUnreadDataJob, | |
252 }; | |
253 | |
254 // The kMockPendingJob uses a slight delay before allowing the connect | |
255 // to complete. | |
256 static const int kPendingConnectDelay = 2; | |
257 | |
258 TestConnectJob(JobType job_type, | |
259 const std::string& group_name, | |
260 const TestClientSocketPoolBase::Request& request, | |
261 base::TimeDelta timeout_duration, | |
262 ConnectJob::Delegate* delegate, | |
263 MockClientSocketFactory* client_socket_factory, | |
264 NetLog* net_log) | |
265 : ConnectJob(group_name, timeout_duration, request.priority(), delegate, | |
266 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), | |
267 job_type_(job_type), | |
268 client_socket_factory_(client_socket_factory), | |
269 load_state_(LOAD_STATE_IDLE), | |
270 store_additional_error_state_(false), | |
271 weak_factory_(this) { | |
272 } | |
273 | |
274 void Signal() { | |
275 DoConnect(waiting_success_, true /* async */, false /* recoverable */); | |
276 } | |
277 | |
278 void set_load_state(LoadState load_state) { load_state_ = load_state; } | |
279 | |
280 // From ConnectJob: | |
281 | |
282 LoadState GetLoadState() const override { return load_state_; } | |
283 | |
284 void GetAdditionalErrorState(ClientSocketHandle* handle) override { | |
285 if (store_additional_error_state_) { | |
286 // Set all of the additional error state fields in some way. | |
287 handle->set_is_ssl_error(true); | |
288 HttpResponseInfo info; | |
289 info.headers = new HttpResponseHeaders(std::string()); | |
290 handle->set_ssl_error_response_info(info); | |
291 } | |
292 } | |
293 | |
294 private: | |
295 // From ConnectJob: | |
296 | |
297 int ConnectInternal() override { | |
298 AddressList ignored; | |
299 client_socket_factory_->CreateTransportClientSocket( | |
300 ignored, NULL, net::NetLog::Source()); | |
301 SetSocket( | |
302 scoped_ptr<StreamSocket>(new MockClientSocket(net_log().net_log()))); | |
303 switch (job_type_) { | |
304 case kMockJob: | |
305 return DoConnect(true /* successful */, false /* sync */, | |
306 false /* recoverable */); | |
307 case kMockFailingJob: | |
308 return DoConnect(false /* error */, false /* sync */, | |
309 false /* recoverable */); | |
310 case kMockPendingJob: | |
311 set_load_state(LOAD_STATE_CONNECTING); | |
312 | |
313 // Depending on execution timings, posting a delayed task can result | |
314 // in the task getting executed the at the earliest possible | |
315 // opportunity or only after returning once from the message loop and | |
316 // then a second call into the message loop. In order to make behavior | |
317 // more deterministic, we change the default delay to 2ms. This should | |
318 // always require us to wait for the second call into the message loop. | |
319 // | |
320 // N.B. The correct fix for this and similar timing problems is to | |
321 // abstract time for the purpose of unittests. Unfortunately, we have | |
322 // a lot of third-party components that directly call the various | |
323 // time functions, so this change would be rather invasive. | |
324 base::MessageLoop::current()->PostDelayedTask( | |
325 FROM_HERE, | |
326 base::Bind(base::IgnoreResult(&TestConnectJob::DoConnect), | |
327 weak_factory_.GetWeakPtr(), | |
328 true /* successful */, | |
329 true /* async */, | |
330 false /* recoverable */), | |
331 base::TimeDelta::FromMilliseconds(kPendingConnectDelay)); | |
332 return ERR_IO_PENDING; | |
333 case kMockPendingFailingJob: | |
334 set_load_state(LOAD_STATE_CONNECTING); | |
335 base::MessageLoop::current()->PostDelayedTask( | |
336 FROM_HERE, | |
337 base::Bind(base::IgnoreResult(&TestConnectJob::DoConnect), | |
338 weak_factory_.GetWeakPtr(), | |
339 false /* error */, | |
340 true /* async */, | |
341 false /* recoverable */), | |
342 base::TimeDelta::FromMilliseconds(2)); | |
343 return ERR_IO_PENDING; | |
344 case kMockWaitingJob: | |
345 set_load_state(LOAD_STATE_CONNECTING); | |
346 client_socket_factory_->WaitForSignal(this); | |
347 waiting_success_ = true; | |
348 return ERR_IO_PENDING; | |
349 case kMockRecoverableJob: | |
350 return DoConnect(false /* error */, false /* sync */, | |
351 true /* recoverable */); | |
352 case kMockPendingRecoverableJob: | |
353 set_load_state(LOAD_STATE_CONNECTING); | |
354 base::MessageLoop::current()->PostDelayedTask( | |
355 FROM_HERE, | |
356 base::Bind(base::IgnoreResult(&TestConnectJob::DoConnect), | |
357 weak_factory_.GetWeakPtr(), | |
358 false /* error */, | |
359 true /* async */, | |
360 true /* recoverable */), | |
361 base::TimeDelta::FromMilliseconds(2)); | |
362 return ERR_IO_PENDING; | |
363 case kMockAdditionalErrorStateJob: | |
364 store_additional_error_state_ = true; | |
365 return DoConnect(false /* error */, false /* sync */, | |
366 false /* recoverable */); | |
367 case kMockPendingAdditionalErrorStateJob: | |
368 set_load_state(LOAD_STATE_CONNECTING); | |
369 store_additional_error_state_ = true; | |
370 base::MessageLoop::current()->PostDelayedTask( | |
371 FROM_HERE, | |
372 base::Bind(base::IgnoreResult(&TestConnectJob::DoConnect), | |
373 weak_factory_.GetWeakPtr(), | |
374 false /* error */, | |
375 true /* async */, | |
376 false /* recoverable */), | |
377 base::TimeDelta::FromMilliseconds(2)); | |
378 return ERR_IO_PENDING; | |
379 case kMockUnreadDataJob: { | |
380 int ret = DoConnect(true /* successful */, false /* sync */, | |
381 false /* recoverable */); | |
382 static_cast<MockClientSocket*>(socket())->set_has_unread_data(true); | |
383 return ret; | |
384 } | |
385 default: | |
386 NOTREACHED(); | |
387 SetSocket(scoped_ptr<StreamSocket>()); | |
388 return ERR_FAILED; | |
389 } | |
390 } | |
391 | |
392 int DoConnect(bool succeed, bool was_async, bool recoverable) { | |
393 int result = OK; | |
394 if (succeed) { | |
395 socket()->Connect(CompletionCallback()); | |
396 } else if (recoverable) { | |
397 result = ERR_PROXY_AUTH_REQUESTED; | |
398 } else { | |
399 result = ERR_CONNECTION_FAILED; | |
400 SetSocket(scoped_ptr<StreamSocket>()); | |
401 } | |
402 | |
403 if (was_async) | |
404 NotifyDelegateOfCompletion(result); | |
405 return result; | |
406 } | |
407 | |
408 bool waiting_success_; | |
409 const JobType job_type_; | |
410 MockClientSocketFactory* const client_socket_factory_; | |
411 LoadState load_state_; | |
412 bool store_additional_error_state_; | |
413 | |
414 base::WeakPtrFactory<TestConnectJob> weak_factory_; | |
415 | |
416 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); | |
417 }; | |
418 | |
419 class TestConnectJobFactory | |
420 : public TestClientSocketPoolBase::ConnectJobFactory { | |
421 public: | |
422 TestConnectJobFactory(MockClientSocketFactory* client_socket_factory, | |
423 NetLog* net_log) | |
424 : job_type_(TestConnectJob::kMockJob), | |
425 job_types_(NULL), | |
426 client_socket_factory_(client_socket_factory), | |
427 net_log_(net_log) { | |
428 } | |
429 | |
430 ~TestConnectJobFactory() override {} | |
431 | |
432 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } | |
433 | |
434 void set_job_types(std::list<TestConnectJob::JobType>* job_types) { | |
435 job_types_ = job_types; | |
436 CHECK(!job_types_->empty()); | |
437 } | |
438 | |
439 void set_timeout_duration(base::TimeDelta timeout_duration) { | |
440 timeout_duration_ = timeout_duration; | |
441 } | |
442 | |
443 // ConnectJobFactory implementation. | |
444 | |
445 scoped_ptr<ConnectJob> NewConnectJob( | |
446 const std::string& group_name, | |
447 const TestClientSocketPoolBase::Request& request, | |
448 ConnectJob::Delegate* delegate) const override { | |
449 EXPECT_TRUE(!job_types_ || !job_types_->empty()); | |
450 TestConnectJob::JobType job_type = job_type_; | |
451 if (job_types_ && !job_types_->empty()) { | |
452 job_type = job_types_->front(); | |
453 job_types_->pop_front(); | |
454 } | |
455 return scoped_ptr<ConnectJob>(new TestConnectJob(job_type, | |
456 group_name, | |
457 request, | |
458 timeout_duration_, | |
459 delegate, | |
460 client_socket_factory_, | |
461 net_log_)); | |
462 } | |
463 | |
464 base::TimeDelta ConnectionTimeout() const override { | |
465 return timeout_duration_; | |
466 } | |
467 | |
468 private: | |
469 TestConnectJob::JobType job_type_; | |
470 std::list<TestConnectJob::JobType>* job_types_; | |
471 base::TimeDelta timeout_duration_; | |
472 MockClientSocketFactory* const client_socket_factory_; | |
473 NetLog* net_log_; | |
474 | |
475 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); | |
476 }; | |
477 | |
478 class TestClientSocketPool : public ClientSocketPool { | |
479 public: | |
480 typedef TestSocketParams SocketParams; | |
481 | |
482 TestClientSocketPool( | |
483 int max_sockets, | |
484 int max_sockets_per_group, | |
485 ClientSocketPoolHistograms* histograms, | |
486 base::TimeDelta unused_idle_socket_timeout, | |
487 base::TimeDelta used_idle_socket_timeout, | |
488 TestClientSocketPoolBase::ConnectJobFactory* connect_job_factory) | |
489 : base_(NULL, max_sockets, max_sockets_per_group, histograms, | |
490 unused_idle_socket_timeout, used_idle_socket_timeout, | |
491 connect_job_factory) {} | |
492 | |
493 ~TestClientSocketPool() override {} | |
494 | |
495 int RequestSocket(const std::string& group_name, | |
496 const void* params, | |
497 net::RequestPriority priority, | |
498 ClientSocketHandle* handle, | |
499 const CompletionCallback& callback, | |
500 const BoundNetLog& net_log) override { | |
501 const scoped_refptr<TestSocketParams>* casted_socket_params = | |
502 static_cast<const scoped_refptr<TestSocketParams>*>(params); | |
503 return base_.RequestSocket(group_name, *casted_socket_params, priority, | |
504 handle, callback, net_log); | |
505 } | |
506 | |
507 void RequestSockets(const std::string& group_name, | |
508 const void* params, | |
509 int num_sockets, | |
510 const BoundNetLog& net_log) override { | |
511 const scoped_refptr<TestSocketParams>* casted_params = | |
512 static_cast<const scoped_refptr<TestSocketParams>*>(params); | |
513 | |
514 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log); | |
515 } | |
516 | |
517 void CancelRequest(const std::string& group_name, | |
518 ClientSocketHandle* handle) override { | |
519 base_.CancelRequest(group_name, handle); | |
520 } | |
521 | |
522 void ReleaseSocket(const std::string& group_name, | |
523 scoped_ptr<StreamSocket> socket, | |
524 int id) override { | |
525 base_.ReleaseSocket(group_name, socket.Pass(), id); | |
526 } | |
527 | |
528 void FlushWithError(int error) override { base_.FlushWithError(error); } | |
529 | |
530 bool IsStalled() const override { return base_.IsStalled(); } | |
531 | |
532 void CloseIdleSockets() override { base_.CloseIdleSockets(); } | |
533 | |
534 int IdleSocketCount() const override { return base_.idle_socket_count(); } | |
535 | |
536 int IdleSocketCountInGroup(const std::string& group_name) const override { | |
537 return base_.IdleSocketCountInGroup(group_name); | |
538 } | |
539 | |
540 LoadState GetLoadState(const std::string& group_name, | |
541 const ClientSocketHandle* handle) const override { | |
542 return base_.GetLoadState(group_name, handle); | |
543 } | |
544 | |
545 void AddHigherLayeredPool(HigherLayeredPool* higher_pool) override { | |
546 base_.AddHigherLayeredPool(higher_pool); | |
547 } | |
548 | |
549 void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) override { | |
550 base_.RemoveHigherLayeredPool(higher_pool); | |
551 } | |
552 | |
553 base::DictionaryValue* GetInfoAsValue( | |
554 const std::string& name, | |
555 const std::string& type, | |
556 bool include_nested_pools) const override { | |
557 return base_.GetInfoAsValue(name, type); | |
558 } | |
559 | |
560 base::TimeDelta ConnectionTimeout() const override { | |
561 return base_.ConnectionTimeout(); | |
562 } | |
563 | |
564 ClientSocketPoolHistograms* histograms() const override { | |
565 return base_.histograms(); | |
566 } | |
567 | |
568 const TestClientSocketPoolBase* base() const { return &base_; } | |
569 | |
570 int NumUnassignedConnectJobsInGroup(const std::string& group_name) const { | |
571 return base_.NumUnassignedConnectJobsInGroup(group_name); | |
572 } | |
573 | |
574 int NumConnectJobsInGroup(const std::string& group_name) const { | |
575 return base_.NumConnectJobsInGroup(group_name); | |
576 } | |
577 | |
578 int NumActiveSocketsInGroup(const std::string& group_name) const { | |
579 return base_.NumActiveSocketsInGroup(group_name); | |
580 } | |
581 | |
582 bool HasGroup(const std::string& group_name) const { | |
583 return base_.HasGroup(group_name); | |
584 } | |
585 | |
586 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); } | |
587 | |
588 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } | |
589 | |
590 bool CloseOneIdleConnectionInHigherLayeredPool() { | |
591 return base_.CloseOneIdleConnectionInHigherLayeredPool(); | |
592 } | |
593 | |
594 private: | |
595 TestClientSocketPoolBase base_; | |
596 | |
597 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); | |
598 }; | |
599 | |
600 } // namespace | |
601 | |
602 namespace { | |
603 | |
604 void MockClientSocketFactory::SignalJobs() { | |
605 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin(); | |
606 it != waiting_jobs_.end(); ++it) { | |
607 (*it)->Signal(); | |
608 } | |
609 waiting_jobs_.clear(); | |
610 } | |
611 | |
612 void MockClientSocketFactory::SignalJob(size_t job) { | |
613 ASSERT_LT(job, waiting_jobs_.size()); | |
614 waiting_jobs_[job]->Signal(); | |
615 waiting_jobs_.erase(waiting_jobs_.begin() + job); | |
616 } | |
617 | |
618 void MockClientSocketFactory::SetJobLoadState(size_t job, | |
619 LoadState load_state) { | |
620 ASSERT_LT(job, waiting_jobs_.size()); | |
621 waiting_jobs_[job]->set_load_state(load_state); | |
622 } | |
623 | |
624 class TestConnectJobDelegate : public ConnectJob::Delegate { | |
625 public: | |
626 TestConnectJobDelegate() | |
627 : have_result_(false), waiting_for_result_(false), result_(OK) {} | |
628 ~TestConnectJobDelegate() override {} | |
629 | |
630 void OnConnectJobComplete(int result, ConnectJob* job) override { | |
631 result_ = result; | |
632 scoped_ptr<ConnectJob> owned_job(job); | |
633 scoped_ptr<StreamSocket> socket = owned_job->PassSocket(); | |
634 // socket.get() should be NULL iff result != OK | |
635 EXPECT_EQ(socket == NULL, result != OK); | |
636 have_result_ = true; | |
637 if (waiting_for_result_) | |
638 base::MessageLoop::current()->Quit(); | |
639 } | |
640 | |
641 int WaitForResult() { | |
642 DCHECK(!waiting_for_result_); | |
643 while (!have_result_) { | |
644 waiting_for_result_ = true; | |
645 base::MessageLoop::current()->Run(); | |
646 waiting_for_result_ = false; | |
647 } | |
648 have_result_ = false; // auto-reset for next callback | |
649 return result_; | |
650 } | |
651 | |
652 private: | |
653 bool have_result_; | |
654 bool waiting_for_result_; | |
655 int result_; | |
656 }; | |
657 | |
658 class ClientSocketPoolBaseTest : public testing::Test { | |
659 protected: | |
660 ClientSocketPoolBaseTest() | |
661 : params_(new TestSocketParams(false /* ignore_limits */)), | |
662 histograms_("ClientSocketPoolTest") { | |
663 connect_backup_jobs_enabled_ = | |
664 internal::ClientSocketPoolBaseHelper::connect_backup_jobs_enabled(); | |
665 internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(true); | |
666 cleanup_timer_enabled_ = | |
667 internal::ClientSocketPoolBaseHelper::cleanup_timer_enabled(); | |
668 } | |
669 | |
670 ~ClientSocketPoolBaseTest() override { | |
671 internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled( | |
672 connect_backup_jobs_enabled_); | |
673 internal::ClientSocketPoolBaseHelper::set_cleanup_timer_enabled( | |
674 cleanup_timer_enabled_); | |
675 } | |
676 | |
677 void CreatePool(int max_sockets, int max_sockets_per_group) { | |
678 CreatePoolWithIdleTimeouts( | |
679 max_sockets, | |
680 max_sockets_per_group, | |
681 ClientSocketPool::unused_idle_socket_timeout(), | |
682 ClientSocketPool::used_idle_socket_timeout()); | |
683 } | |
684 | |
685 void CreatePoolWithIdleTimeouts( | |
686 int max_sockets, int max_sockets_per_group, | |
687 base::TimeDelta unused_idle_socket_timeout, | |
688 base::TimeDelta used_idle_socket_timeout) { | |
689 DCHECK(!pool_.get()); | |
690 connect_job_factory_ = new TestConnectJobFactory(&client_socket_factory_, | |
691 &net_log_); | |
692 pool_.reset(new TestClientSocketPool(max_sockets, | |
693 max_sockets_per_group, | |
694 &histograms_, | |
695 unused_idle_socket_timeout, | |
696 used_idle_socket_timeout, | |
697 connect_job_factory_)); | |
698 } | |
699 | |
700 int StartRequestWithParams( | |
701 const std::string& group_name, | |
702 RequestPriority priority, | |
703 const scoped_refptr<TestSocketParams>& params) { | |
704 return test_base_.StartRequestUsingPool( | |
705 pool_.get(), group_name, priority, params); | |
706 } | |
707 | |
708 int StartRequest(const std::string& group_name, RequestPriority priority) { | |
709 return StartRequestWithParams(group_name, priority, params_); | |
710 } | |
711 | |
712 int GetOrderOfRequest(size_t index) const { | |
713 return test_base_.GetOrderOfRequest(index); | |
714 } | |
715 | |
716 bool ReleaseOneConnection(ClientSocketPoolTest::KeepAlive keep_alive) { | |
717 return test_base_.ReleaseOneConnection(keep_alive); | |
718 } | |
719 | |
720 void ReleaseAllConnections(ClientSocketPoolTest::KeepAlive keep_alive) { | |
721 test_base_.ReleaseAllConnections(keep_alive); | |
722 } | |
723 | |
724 TestSocketRequest* request(int i) { return test_base_.request(i); } | |
725 size_t requests_size() const { return test_base_.requests_size(); } | |
726 ScopedVector<TestSocketRequest>* requests() { return test_base_.requests(); } | |
727 size_t completion_count() const { return test_base_.completion_count(); } | |
728 | |
729 CapturingNetLog net_log_; | |
730 bool connect_backup_jobs_enabled_; | |
731 bool cleanup_timer_enabled_; | |
732 MockClientSocketFactory client_socket_factory_; | |
733 TestConnectJobFactory* connect_job_factory_; | |
734 scoped_refptr<TestSocketParams> params_; | |
735 ClientSocketPoolHistograms histograms_; | |
736 scoped_ptr<TestClientSocketPool> pool_; | |
737 ClientSocketPoolTest test_base_; | |
738 }; | |
739 | |
740 // Even though a timeout is specified, it doesn't time out on a synchronous | |
741 // completion. | |
742 TEST_F(ClientSocketPoolBaseTest, ConnectJob_NoTimeoutOnSynchronousCompletion) { | |
743 TestConnectJobDelegate delegate; | |
744 ClientSocketHandle ignored; | |
745 TestClientSocketPoolBase::Request request( | |
746 &ignored, CompletionCallback(), DEFAULT_PRIORITY, | |
747 internal::ClientSocketPoolBaseHelper::NORMAL, | |
748 false, params_, BoundNetLog()); | |
749 scoped_ptr<TestConnectJob> job( | |
750 new TestConnectJob(TestConnectJob::kMockJob, | |
751 "a", | |
752 request, | |
753 base::TimeDelta::FromMicroseconds(1), | |
754 &delegate, | |
755 &client_socket_factory_, | |
756 NULL)); | |
757 EXPECT_EQ(OK, job->Connect()); | |
758 } | |
759 | |
760 TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) { | |
761 TestConnectJobDelegate delegate; | |
762 ClientSocketHandle ignored; | |
763 CapturingNetLog log; | |
764 | |
765 TestClientSocketPoolBase::Request request( | |
766 &ignored, CompletionCallback(), DEFAULT_PRIORITY, | |
767 internal::ClientSocketPoolBaseHelper::NORMAL, | |
768 false, params_, BoundNetLog()); | |
769 // Deleted by TestConnectJobDelegate. | |
770 TestConnectJob* job = | |
771 new TestConnectJob(TestConnectJob::kMockPendingJob, | |
772 "a", | |
773 request, | |
774 base::TimeDelta::FromMicroseconds(1), | |
775 &delegate, | |
776 &client_socket_factory_, | |
777 &log); | |
778 ASSERT_EQ(ERR_IO_PENDING, job->Connect()); | |
779 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); | |
780 EXPECT_EQ(ERR_TIMED_OUT, delegate.WaitForResult()); | |
781 | |
782 CapturingNetLog::CapturedEntryList entries; | |
783 log.GetEntries(&entries); | |
784 | |
785 EXPECT_EQ(6u, entries.size()); | |
786 EXPECT_TRUE(LogContainsBeginEvent( | |
787 entries, 0, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB)); | |
788 EXPECT_TRUE(LogContainsBeginEvent( | |
789 entries, 1, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT)); | |
790 EXPECT_TRUE(LogContainsEvent( | |
791 entries, 2, NetLog::TYPE_CONNECT_JOB_SET_SOCKET, | |
792 NetLog::PHASE_NONE)); | |
793 EXPECT_TRUE(LogContainsEvent( | |
794 entries, 3, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT, | |
795 NetLog::PHASE_NONE)); | |
796 EXPECT_TRUE(LogContainsEndEvent( | |
797 entries, 4, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT)); | |
798 EXPECT_TRUE(LogContainsEndEvent( | |
799 entries, 5, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB)); | |
800 } | |
801 | |
802 TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) { | |
803 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
804 | |
805 TestCompletionCallback callback; | |
806 ClientSocketHandle handle; | |
807 CapturingBoundNetLog log; | |
808 TestLoadTimingInfoNotConnected(handle); | |
809 | |
810 EXPECT_EQ(OK, | |
811 handle.Init("a", | |
812 params_, | |
813 DEFAULT_PRIORITY, | |
814 callback.callback(), | |
815 pool_.get(), | |
816 log.bound())); | |
817 EXPECT_TRUE(handle.is_initialized()); | |
818 EXPECT_TRUE(handle.socket()); | |
819 TestLoadTimingInfoConnectedNotReused(handle); | |
820 | |
821 handle.Reset(); | |
822 TestLoadTimingInfoNotConnected(handle); | |
823 | |
824 CapturingNetLog::CapturedEntryList entries; | |
825 log.GetEntries(&entries); | |
826 | |
827 EXPECT_EQ(4u, entries.size()); | |
828 EXPECT_TRUE(LogContainsBeginEvent( | |
829 entries, 0, NetLog::TYPE_SOCKET_POOL)); | |
830 EXPECT_TRUE(LogContainsEvent( | |
831 entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB, | |
832 NetLog::PHASE_NONE)); | |
833 EXPECT_TRUE(LogContainsEvent( | |
834 entries, 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, | |
835 NetLog::PHASE_NONE)); | |
836 EXPECT_TRUE(LogContainsEndEvent( | |
837 entries, 3, NetLog::TYPE_SOCKET_POOL)); | |
838 } | |
839 | |
840 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { | |
841 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
842 | |
843 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | |
844 CapturingBoundNetLog log; | |
845 | |
846 ClientSocketHandle handle; | |
847 TestCompletionCallback callback; | |
848 // Set the additional error state members to ensure that they get cleared. | |
849 handle.set_is_ssl_error(true); | |
850 HttpResponseInfo info; | |
851 info.headers = new HttpResponseHeaders(std::string()); | |
852 handle.set_ssl_error_response_info(info); | |
853 EXPECT_EQ(ERR_CONNECTION_FAILED, | |
854 handle.Init("a", | |
855 params_, | |
856 DEFAULT_PRIORITY, | |
857 callback.callback(), | |
858 pool_.get(), | |
859 log.bound())); | |
860 EXPECT_FALSE(handle.socket()); | |
861 EXPECT_FALSE(handle.is_ssl_error()); | |
862 EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL); | |
863 TestLoadTimingInfoNotConnected(handle); | |
864 | |
865 CapturingNetLog::CapturedEntryList entries; | |
866 log.GetEntries(&entries); | |
867 | |
868 EXPECT_EQ(3u, entries.size()); | |
869 EXPECT_TRUE(LogContainsBeginEvent( | |
870 entries, 0, NetLog::TYPE_SOCKET_POOL)); | |
871 EXPECT_TRUE(LogContainsEvent( | |
872 entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB, | |
873 NetLog::PHASE_NONE)); | |
874 EXPECT_TRUE(LogContainsEndEvent( | |
875 entries, 2, NetLog::TYPE_SOCKET_POOL)); | |
876 } | |
877 | |
878 TEST_F(ClientSocketPoolBaseTest, TotalLimit) { | |
879 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
880 | |
881 // TODO(eroman): Check that the NetLog contains this event. | |
882 | |
883 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
884 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
885 EXPECT_EQ(OK, StartRequest("c", DEFAULT_PRIORITY)); | |
886 EXPECT_EQ(OK, StartRequest("d", DEFAULT_PRIORITY)); | |
887 | |
888 EXPECT_EQ(static_cast<int>(requests_size()), | |
889 client_socket_factory_.allocation_count()); | |
890 EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count()); | |
891 | |
892 EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", DEFAULT_PRIORITY)); | |
893 EXPECT_EQ(ERR_IO_PENDING, StartRequest("f", DEFAULT_PRIORITY)); | |
894 EXPECT_EQ(ERR_IO_PENDING, StartRequest("g", DEFAULT_PRIORITY)); | |
895 | |
896 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
897 | |
898 EXPECT_EQ(static_cast<int>(requests_size()), | |
899 client_socket_factory_.allocation_count()); | |
900 EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count()); | |
901 | |
902 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
903 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
904 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
905 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
906 EXPECT_EQ(5, GetOrderOfRequest(5)); | |
907 EXPECT_EQ(6, GetOrderOfRequest(6)); | |
908 EXPECT_EQ(7, GetOrderOfRequest(7)); | |
909 | |
910 // Make sure we test order of all requests made. | |
911 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(8)); | |
912 } | |
913 | |
914 TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) { | |
915 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
916 | |
917 // TODO(eroman): Check that the NetLog contains this event. | |
918 | |
919 // Reach all limits: max total sockets, and max sockets per group. | |
920 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
921 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
922 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
923 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
924 | |
925 EXPECT_EQ(static_cast<int>(requests_size()), | |
926 client_socket_factory_.allocation_count()); | |
927 EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count()); | |
928 | |
929 // Now create a new group and verify that we don't starve it. | |
930 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", DEFAULT_PRIORITY)); | |
931 | |
932 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
933 | |
934 EXPECT_EQ(static_cast<int>(requests_size()), | |
935 client_socket_factory_.allocation_count()); | |
936 EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count()); | |
937 | |
938 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
939 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
940 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
941 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
942 EXPECT_EQ(5, GetOrderOfRequest(5)); | |
943 | |
944 // Make sure we test order of all requests made. | |
945 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(6)); | |
946 } | |
947 | |
948 TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsPriority) { | |
949 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
950 | |
951 EXPECT_EQ(OK, StartRequest("b", LOWEST)); | |
952 EXPECT_EQ(OK, StartRequest("a", MEDIUM)); | |
953 EXPECT_EQ(OK, StartRequest("b", HIGHEST)); | |
954 EXPECT_EQ(OK, StartRequest("a", LOWEST)); | |
955 | |
956 EXPECT_EQ(static_cast<int>(requests_size()), | |
957 client_socket_factory_.allocation_count()); | |
958 | |
959 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", LOWEST)); | |
960 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM)); | |
961 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", HIGHEST)); | |
962 | |
963 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
964 | |
965 EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count()); | |
966 | |
967 // First 4 requests don't have to wait, and finish in order. | |
968 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
969 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
970 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
971 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
972 | |
973 // Request ("b", HIGHEST) has the highest priority, then ("a", MEDIUM), | |
974 // and then ("c", LOWEST). | |
975 EXPECT_EQ(7, GetOrderOfRequest(5)); | |
976 EXPECT_EQ(6, GetOrderOfRequest(6)); | |
977 EXPECT_EQ(5, GetOrderOfRequest(7)); | |
978 | |
979 // Make sure we test order of all requests made. | |
980 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(9)); | |
981 } | |
982 | |
983 TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) { | |
984 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
985 | |
986 EXPECT_EQ(OK, StartRequest("a", LOWEST)); | |
987 EXPECT_EQ(OK, StartRequest("a", LOW)); | |
988 EXPECT_EQ(OK, StartRequest("b", HIGHEST)); | |
989 EXPECT_EQ(OK, StartRequest("b", MEDIUM)); | |
990 | |
991 EXPECT_EQ(static_cast<int>(requests_size()), | |
992 client_socket_factory_.allocation_count()); | |
993 | |
994 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", MEDIUM)); | |
995 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW)); | |
996 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", HIGHEST)); | |
997 | |
998 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
999 | |
1000 EXPECT_EQ(static_cast<int>(requests_size()), | |
1001 client_socket_factory_.allocation_count()); | |
1002 EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count()); | |
1003 | |
1004 // First 4 requests don't have to wait, and finish in order. | |
1005 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
1006 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
1007 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
1008 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
1009 | |
1010 // Request ("b", 7) has the highest priority, but we can't make new socket for | |
1011 // group "b", because it has reached the per-group limit. Then we make | |
1012 // socket for ("c", 6), because it has higher priority than ("a", 4), | |
1013 // and we still can't make a socket for group "b". | |
1014 EXPECT_EQ(5, GetOrderOfRequest(5)); | |
1015 EXPECT_EQ(6, GetOrderOfRequest(6)); | |
1016 EXPECT_EQ(7, GetOrderOfRequest(7)); | |
1017 | |
1018 // Make sure we test order of all requests made. | |
1019 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(8)); | |
1020 } | |
1021 | |
1022 // Make sure that we count connecting sockets against the total limit. | |
1023 TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) { | |
1024 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1025 | |
1026 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1027 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
1028 EXPECT_EQ(OK, StartRequest("c", DEFAULT_PRIORITY)); | |
1029 | |
1030 // Create one asynchronous request. | |
1031 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1032 EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", DEFAULT_PRIORITY)); | |
1033 | |
1034 // We post all of our delayed tasks with a 2ms delay. I.e. they don't | |
1035 // actually become pending until 2ms after they have been created. In order | |
1036 // to flush all tasks, we need to wait so that we know there are no | |
1037 // soon-to-be-pending tasks waiting. | |
1038 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | |
1039 base::MessageLoop::current()->RunUntilIdle(); | |
1040 | |
1041 // The next synchronous request should wait for its turn. | |
1042 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
1043 EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", DEFAULT_PRIORITY)); | |
1044 | |
1045 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
1046 | |
1047 EXPECT_EQ(static_cast<int>(requests_size()), | |
1048 client_socket_factory_.allocation_count()); | |
1049 | |
1050 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
1051 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
1052 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
1053 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
1054 EXPECT_EQ(5, GetOrderOfRequest(5)); | |
1055 | |
1056 // Make sure we test order of all requests made. | |
1057 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(6)); | |
1058 } | |
1059 | |
1060 TEST_F(ClientSocketPoolBaseTest, CorrectlyCountStalledGroups) { | |
1061 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
1062 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
1063 | |
1064 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1065 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1066 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1067 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1068 | |
1069 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
1070 | |
1071 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
1072 | |
1073 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", DEFAULT_PRIORITY)); | |
1074 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", DEFAULT_PRIORITY)); | |
1075 | |
1076 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
1077 | |
1078 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE)); | |
1079 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); | |
1080 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE)); | |
1081 EXPECT_EQ(kDefaultMaxSockets + 2, client_socket_factory_.allocation_count()); | |
1082 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE)); | |
1083 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE)); | |
1084 EXPECT_EQ(kDefaultMaxSockets + 2, client_socket_factory_.allocation_count()); | |
1085 } | |
1086 | |
1087 TEST_F(ClientSocketPoolBaseTest, StallAndThenCancelAndTriggerAvailableSocket) { | |
1088 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
1089 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1090 | |
1091 ClientSocketHandle handle; | |
1092 TestCompletionCallback callback; | |
1093 EXPECT_EQ(ERR_IO_PENDING, | |
1094 handle.Init("a", | |
1095 params_, | |
1096 DEFAULT_PRIORITY, | |
1097 callback.callback(), | |
1098 pool_.get(), | |
1099 BoundNetLog())); | |
1100 | |
1101 ClientSocketHandle handles[4]; | |
1102 for (size_t i = 0; i < arraysize(handles); ++i) { | |
1103 TestCompletionCallback callback; | |
1104 EXPECT_EQ(ERR_IO_PENDING, | |
1105 handles[i].Init("b", | |
1106 params_, | |
1107 DEFAULT_PRIORITY, | |
1108 callback.callback(), | |
1109 pool_.get(), | |
1110 BoundNetLog())); | |
1111 } | |
1112 | |
1113 // One will be stalled, cancel all the handles now. | |
1114 // This should hit the OnAvailableSocketSlot() code where we previously had | |
1115 // stalled groups, but no longer have any. | |
1116 for (size_t i = 0; i < arraysize(handles); ++i) | |
1117 handles[i].Reset(); | |
1118 } | |
1119 | |
1120 TEST_F(ClientSocketPoolBaseTest, CancelStalledSocketAtSocketLimit) { | |
1121 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1122 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
1123 | |
1124 { | |
1125 ClientSocketHandle handles[kDefaultMaxSockets]; | |
1126 TestCompletionCallback callbacks[kDefaultMaxSockets]; | |
1127 for (int i = 0; i < kDefaultMaxSockets; ++i) { | |
1128 EXPECT_EQ(OK, handles[i].Init(base::IntToString(i), | |
1129 params_, | |
1130 DEFAULT_PRIORITY, | |
1131 callbacks[i].callback(), | |
1132 pool_.get(), | |
1133 BoundNetLog())); | |
1134 } | |
1135 | |
1136 // Force a stalled group. | |
1137 ClientSocketHandle stalled_handle; | |
1138 TestCompletionCallback callback; | |
1139 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", | |
1140 params_, | |
1141 DEFAULT_PRIORITY, | |
1142 callback.callback(), | |
1143 pool_.get(), | |
1144 BoundNetLog())); | |
1145 | |
1146 // Cancel the stalled request. | |
1147 stalled_handle.Reset(); | |
1148 | |
1149 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
1150 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
1151 | |
1152 // Dropping out of scope will close all handles and return them to idle. | |
1153 } | |
1154 | |
1155 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
1156 EXPECT_EQ(kDefaultMaxSockets, pool_->IdleSocketCount()); | |
1157 } | |
1158 | |
1159 TEST_F(ClientSocketPoolBaseTest, CancelPendingSocketAtSocketLimit) { | |
1160 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1161 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
1162 | |
1163 { | |
1164 ClientSocketHandle handles[kDefaultMaxSockets]; | |
1165 for (int i = 0; i < kDefaultMaxSockets; ++i) { | |
1166 TestCompletionCallback callback; | |
1167 EXPECT_EQ(ERR_IO_PENDING, handles[i].Init(base::IntToString(i), | |
1168 params_, | |
1169 DEFAULT_PRIORITY, | |
1170 callback.callback(), | |
1171 pool_.get(), | |
1172 BoundNetLog())); | |
1173 } | |
1174 | |
1175 // Force a stalled group. | |
1176 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1177 ClientSocketHandle stalled_handle; | |
1178 TestCompletionCallback callback; | |
1179 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", | |
1180 params_, | |
1181 DEFAULT_PRIORITY, | |
1182 callback.callback(), | |
1183 pool_.get(), | |
1184 BoundNetLog())); | |
1185 | |
1186 // Since it is stalled, it should have no connect jobs. | |
1187 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("foo")); | |
1188 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("foo")); | |
1189 | |
1190 // Cancel the stalled request. | |
1191 handles[0].Reset(); | |
1192 | |
1193 // Now we should have a connect job. | |
1194 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("foo")); | |
1195 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("foo")); | |
1196 | |
1197 // The stalled socket should connect. | |
1198 EXPECT_EQ(OK, callback.WaitForResult()); | |
1199 | |
1200 EXPECT_EQ(kDefaultMaxSockets + 1, | |
1201 client_socket_factory_.allocation_count()); | |
1202 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
1203 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("foo")); | |
1204 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("foo")); | |
1205 | |
1206 // Dropping out of scope will close all handles and return them to idle. | |
1207 } | |
1208 | |
1209 EXPECT_EQ(1, pool_->IdleSocketCount()); | |
1210 } | |
1211 | |
1212 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { | |
1213 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1214 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
1215 | |
1216 ClientSocketHandle stalled_handle; | |
1217 TestCompletionCallback callback; | |
1218 { | |
1219 EXPECT_FALSE(pool_->IsStalled()); | |
1220 ClientSocketHandle handles[kDefaultMaxSockets]; | |
1221 for (int i = 0; i < kDefaultMaxSockets; ++i) { | |
1222 TestCompletionCallback callback; | |
1223 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf( | |
1224 "Take 2: %d", i), | |
1225 params_, | |
1226 DEFAULT_PRIORITY, | |
1227 callback.callback(), | |
1228 pool_.get(), | |
1229 BoundNetLog())); | |
1230 } | |
1231 | |
1232 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
1233 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
1234 EXPECT_FALSE(pool_->IsStalled()); | |
1235 | |
1236 // Now we will hit the socket limit. | |
1237 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", | |
1238 params_, | |
1239 DEFAULT_PRIORITY, | |
1240 callback.callback(), | |
1241 pool_.get(), | |
1242 BoundNetLog())); | |
1243 EXPECT_TRUE(pool_->IsStalled()); | |
1244 | |
1245 // Dropping out of scope will close all handles and return them to idle. | |
1246 } | |
1247 | |
1248 // But if we wait for it, the released idle sockets will be closed in | |
1249 // preference of the waiting request. | |
1250 EXPECT_EQ(OK, callback.WaitForResult()); | |
1251 | |
1252 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); | |
1253 EXPECT_EQ(3, pool_->IdleSocketCount()); | |
1254 } | |
1255 | |
1256 // Regression test for http://crbug.com/40952. | |
1257 TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) { | |
1258 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1259 pool_->EnableConnectBackupJobs(); | |
1260 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
1261 | |
1262 for (int i = 0; i < kDefaultMaxSockets; ++i) { | |
1263 ClientSocketHandle handle; | |
1264 TestCompletionCallback callback; | |
1265 EXPECT_EQ(OK, handle.Init(base::IntToString(i), | |
1266 params_, | |
1267 DEFAULT_PRIORITY, | |
1268 callback.callback(), | |
1269 pool_.get(), | |
1270 BoundNetLog())); | |
1271 } | |
1272 | |
1273 // Flush all the DoReleaseSocket tasks. | |
1274 base::MessageLoop::current()->RunUntilIdle(); | |
1275 | |
1276 // Stall a group. Set a pending job so it'll trigger a backup job if we don't | |
1277 // reuse a socket. | |
1278 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1279 ClientSocketHandle handle; | |
1280 TestCompletionCallback callback; | |
1281 | |
1282 // "0" is special here, since it should be the first entry in the sorted map, | |
1283 // which is the one which we would close an idle socket for. We shouldn't | |
1284 // close an idle socket though, since we should reuse the idle socket. | |
1285 EXPECT_EQ(OK, handle.Init("0", | |
1286 params_, | |
1287 DEFAULT_PRIORITY, | |
1288 callback.callback(), | |
1289 pool_.get(), | |
1290 BoundNetLog())); | |
1291 | |
1292 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
1293 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->IdleSocketCount()); | |
1294 } | |
1295 | |
1296 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { | |
1297 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1298 | |
1299 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1300 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1301 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", IDLE)); | |
1302 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1303 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM)); | |
1304 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST)); | |
1305 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW)); | |
1306 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1307 | |
1308 ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE); | |
1309 | |
1310 EXPECT_EQ(kDefaultMaxSocketsPerGroup, | |
1311 client_socket_factory_.allocation_count()); | |
1312 EXPECT_EQ(requests_size() - kDefaultMaxSocketsPerGroup, | |
1313 completion_count()); | |
1314 | |
1315 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
1316 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
1317 EXPECT_EQ(8, GetOrderOfRequest(3)); | |
1318 EXPECT_EQ(6, GetOrderOfRequest(4)); | |
1319 EXPECT_EQ(4, GetOrderOfRequest(5)); | |
1320 EXPECT_EQ(3, GetOrderOfRequest(6)); | |
1321 EXPECT_EQ(5, GetOrderOfRequest(7)); | |
1322 EXPECT_EQ(7, GetOrderOfRequest(8)); | |
1323 | |
1324 // Make sure we test order of all requests made. | |
1325 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(9)); | |
1326 } | |
1327 | |
1328 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { | |
1329 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1330 | |
1331 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1332 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1333 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1334 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM)); | |
1335 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST)); | |
1336 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW)); | |
1337 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1338 | |
1339 ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); | |
1340 | |
1341 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_size(); ++i) | |
1342 EXPECT_EQ(OK, request(i)->WaitForResult()); | |
1343 | |
1344 EXPECT_EQ(static_cast<int>(requests_size()), | |
1345 client_socket_factory_.allocation_count()); | |
1346 EXPECT_EQ(requests_size() - kDefaultMaxSocketsPerGroup, | |
1347 completion_count()); | |
1348 } | |
1349 | |
1350 // This test will start up a RequestSocket() and then immediately Cancel() it. | |
1351 // The pending connect job will be cancelled and should not call back into | |
1352 // ClientSocketPoolBase. | |
1353 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { | |
1354 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1355 | |
1356 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1357 ClientSocketHandle handle; | |
1358 TestCompletionCallback callback; | |
1359 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
1360 params_, | |
1361 DEFAULT_PRIORITY, | |
1362 callback.callback(), | |
1363 pool_.get(), | |
1364 BoundNetLog())); | |
1365 handle.Reset(); | |
1366 } | |
1367 | |
1368 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { | |
1369 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1370 | |
1371 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1372 ClientSocketHandle handle; | |
1373 TestCompletionCallback callback; | |
1374 | |
1375 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
1376 params_, | |
1377 DEFAULT_PRIORITY, | |
1378 callback.callback(), | |
1379 pool_.get(), | |
1380 BoundNetLog())); | |
1381 | |
1382 handle.Reset(); | |
1383 | |
1384 TestCompletionCallback callback2; | |
1385 EXPECT_EQ(ERR_IO_PENDING, | |
1386 handle.Init("a", | |
1387 params_, | |
1388 DEFAULT_PRIORITY, | |
1389 callback2.callback(), | |
1390 pool_.get(), | |
1391 BoundNetLog())); | |
1392 | |
1393 EXPECT_EQ(OK, callback2.WaitForResult()); | |
1394 EXPECT_FALSE(callback.have_result()); | |
1395 | |
1396 handle.Reset(); | |
1397 } | |
1398 | |
1399 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { | |
1400 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1401 | |
1402 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1403 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1404 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1405 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM)); | |
1406 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST)); | |
1407 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW)); | |
1408 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1409 | |
1410 // Cancel a request. | |
1411 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2; | |
1412 EXPECT_FALSE((*requests())[index_to_cancel]->handle()->is_initialized()); | |
1413 (*requests())[index_to_cancel]->handle()->Reset(); | |
1414 | |
1415 ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE); | |
1416 | |
1417 EXPECT_EQ(kDefaultMaxSocketsPerGroup, | |
1418 client_socket_factory_.allocation_count()); | |
1419 EXPECT_EQ(requests_size() - kDefaultMaxSocketsPerGroup - 1, | |
1420 completion_count()); | |
1421 | |
1422 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
1423 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
1424 EXPECT_EQ(5, GetOrderOfRequest(3)); | |
1425 EXPECT_EQ(3, GetOrderOfRequest(4)); | |
1426 EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, | |
1427 GetOrderOfRequest(5)); // Canceled request. | |
1428 EXPECT_EQ(4, GetOrderOfRequest(6)); | |
1429 EXPECT_EQ(6, GetOrderOfRequest(7)); | |
1430 | |
1431 // Make sure we test order of all requests made. | |
1432 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(8)); | |
1433 } | |
1434 | |
1435 class RequestSocketCallback : public TestCompletionCallbackBase { | |
1436 public: | |
1437 RequestSocketCallback(ClientSocketHandle* handle, | |
1438 TestClientSocketPool* pool, | |
1439 TestConnectJobFactory* test_connect_job_factory, | |
1440 TestConnectJob::JobType next_job_type) | |
1441 : handle_(handle), | |
1442 pool_(pool), | |
1443 within_callback_(false), | |
1444 test_connect_job_factory_(test_connect_job_factory), | |
1445 next_job_type_(next_job_type), | |
1446 callback_(base::Bind(&RequestSocketCallback::OnComplete, | |
1447 base::Unretained(this))) { | |
1448 } | |
1449 | |
1450 ~RequestSocketCallback() override {} | |
1451 | |
1452 const CompletionCallback& callback() const { return callback_; } | |
1453 | |
1454 private: | |
1455 void OnComplete(int result) { | |
1456 SetResult(result); | |
1457 ASSERT_EQ(OK, result); | |
1458 | |
1459 if (!within_callback_) { | |
1460 test_connect_job_factory_->set_job_type(next_job_type_); | |
1461 | |
1462 // Don't allow reuse of the socket. Disconnect it and then release it and | |
1463 // run through the MessageLoop once to get it completely released. | |
1464 handle_->socket()->Disconnect(); | |
1465 handle_->Reset(); | |
1466 { | |
1467 // TODO: Resolve conflicting intentions of stopping recursion with the | |
1468 // |!within_callback_| test (above) and the call to |RunUntilIdle()| | |
1469 // below. http://crbug.com/114130. | |
1470 base::MessageLoop::ScopedNestableTaskAllower allow( | |
1471 base::MessageLoop::current()); | |
1472 base::MessageLoop::current()->RunUntilIdle(); | |
1473 } | |
1474 within_callback_ = true; | |
1475 TestCompletionCallback next_job_callback; | |
1476 scoped_refptr<TestSocketParams> params( | |
1477 new TestSocketParams(false /* ignore_limits */)); | |
1478 int rv = handle_->Init("a", | |
1479 params, | |
1480 DEFAULT_PRIORITY, | |
1481 next_job_callback.callback(), | |
1482 pool_, | |
1483 BoundNetLog()); | |
1484 switch (next_job_type_) { | |
1485 case TestConnectJob::kMockJob: | |
1486 EXPECT_EQ(OK, rv); | |
1487 break; | |
1488 case TestConnectJob::kMockPendingJob: | |
1489 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1490 | |
1491 // For pending jobs, wait for new socket to be created. This makes | |
1492 // sure there are no more pending operations nor any unclosed sockets | |
1493 // when the test finishes. | |
1494 // We need to give it a little bit of time to run, so that all the | |
1495 // operations that happen on timers (e.g. cleanup of idle | |
1496 // connections) can execute. | |
1497 { | |
1498 base::MessageLoop::ScopedNestableTaskAllower allow( | |
1499 base::MessageLoop::current()); | |
1500 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | |
1501 EXPECT_EQ(OK, next_job_callback.WaitForResult()); | |
1502 } | |
1503 break; | |
1504 default: | |
1505 FAIL() << "Unexpected job type: " << next_job_type_; | |
1506 break; | |
1507 } | |
1508 } | |
1509 } | |
1510 | |
1511 ClientSocketHandle* const handle_; | |
1512 TestClientSocketPool* const pool_; | |
1513 bool within_callback_; | |
1514 TestConnectJobFactory* const test_connect_job_factory_; | |
1515 TestConnectJob::JobType next_job_type_; | |
1516 CompletionCallback callback_; | |
1517 }; | |
1518 | |
1519 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { | |
1520 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1521 | |
1522 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1523 ClientSocketHandle handle; | |
1524 RequestSocketCallback callback( | |
1525 &handle, pool_.get(), connect_job_factory_, | |
1526 TestConnectJob::kMockPendingJob); | |
1527 int rv = handle.Init("a", | |
1528 params_, | |
1529 DEFAULT_PRIORITY, | |
1530 callback.callback(), | |
1531 pool_.get(), | |
1532 BoundNetLog()); | |
1533 ASSERT_EQ(ERR_IO_PENDING, rv); | |
1534 | |
1535 EXPECT_EQ(OK, callback.WaitForResult()); | |
1536 } | |
1537 | |
1538 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { | |
1539 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1540 | |
1541 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1542 ClientSocketHandle handle; | |
1543 RequestSocketCallback callback( | |
1544 &handle, pool_.get(), connect_job_factory_, TestConnectJob::kMockJob); | |
1545 int rv = handle.Init("a", | |
1546 params_, | |
1547 DEFAULT_PRIORITY, | |
1548 callback.callback(), | |
1549 pool_.get(), | |
1550 BoundNetLog()); | |
1551 ASSERT_EQ(ERR_IO_PENDING, rv); | |
1552 | |
1553 EXPECT_EQ(OK, callback.WaitForResult()); | |
1554 } | |
1555 | |
1556 // Make sure that pending requests get serviced after active requests get | |
1557 // cancelled. | |
1558 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { | |
1559 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1560 | |
1561 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1562 | |
1563 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1564 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1565 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1566 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1567 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1568 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1569 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1570 | |
1571 // Now, kDefaultMaxSocketsPerGroup requests should be active. | |
1572 // Let's cancel them. | |
1573 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) { | |
1574 ASSERT_FALSE(request(i)->handle()->is_initialized()); | |
1575 request(i)->handle()->Reset(); | |
1576 } | |
1577 | |
1578 // Let's wait for the rest to complete now. | |
1579 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_size(); ++i) { | |
1580 EXPECT_EQ(OK, request(i)->WaitForResult()); | |
1581 request(i)->handle()->Reset(); | |
1582 } | |
1583 | |
1584 EXPECT_EQ(requests_size() - kDefaultMaxSocketsPerGroup, | |
1585 completion_count()); | |
1586 } | |
1587 | |
1588 // Make sure that pending requests get serviced after active requests fail. | |
1589 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { | |
1590 const size_t kMaxSockets = 5; | |
1591 CreatePool(kMaxSockets, kDefaultMaxSocketsPerGroup); | |
1592 | |
1593 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | |
1594 | |
1595 const size_t kNumberOfRequests = 2 * kDefaultMaxSocketsPerGroup + 1; | |
1596 ASSERT_LE(kNumberOfRequests, kMaxSockets); // Otherwise the test will hang. | |
1597 | |
1598 // Queue up all the requests | |
1599 for (size_t i = 0; i < kNumberOfRequests; ++i) | |
1600 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1601 | |
1602 for (size_t i = 0; i < kNumberOfRequests; ++i) | |
1603 EXPECT_EQ(ERR_CONNECTION_FAILED, request(i)->WaitForResult()); | |
1604 } | |
1605 | |
1606 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) { | |
1607 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1608 | |
1609 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1610 | |
1611 ClientSocketHandle handle; | |
1612 TestCompletionCallback callback; | |
1613 int rv = handle.Init("a", | |
1614 params_, | |
1615 DEFAULT_PRIORITY, | |
1616 callback.callback(), | |
1617 pool_.get(), | |
1618 BoundNetLog()); | |
1619 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1620 | |
1621 // Cancel the active request. | |
1622 handle.Reset(); | |
1623 | |
1624 rv = handle.Init("a", | |
1625 params_, | |
1626 DEFAULT_PRIORITY, | |
1627 callback.callback(), | |
1628 pool_.get(), | |
1629 BoundNetLog()); | |
1630 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1631 EXPECT_EQ(OK, callback.WaitForResult()); | |
1632 | |
1633 EXPECT_FALSE(handle.is_reused()); | |
1634 TestLoadTimingInfoConnectedNotReused(handle); | |
1635 EXPECT_EQ(2, client_socket_factory_.allocation_count()); | |
1636 } | |
1637 | |
1638 // Regression test for http://crbug.com/17985. | |
1639 TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) { | |
1640 const int kMaxSockets = 3; | |
1641 const int kMaxSocketsPerGroup = 2; | |
1642 CreatePool(kMaxSockets, kMaxSocketsPerGroup); | |
1643 | |
1644 const RequestPriority kHighPriority = HIGHEST; | |
1645 | |
1646 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1647 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
1648 | |
1649 // This is going to be a pending request in an otherwise empty group. | |
1650 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
1651 | |
1652 // Reach the maximum socket limit. | |
1653 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
1654 | |
1655 // Create a stalled group with high priorities. | |
1656 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority)); | |
1657 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority)); | |
1658 | |
1659 // Release the first two sockets from "a". Because this is a keepalive, | |
1660 // the first release will unblock the pending request for "a". The | |
1661 // second release will unblock a request for "c", becaue it is the next | |
1662 // high priority socket. | |
1663 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE)); | |
1664 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE)); | |
1665 | |
1666 // Closing idle sockets should not get us into trouble, but in the bug | |
1667 // we were hitting a CHECK here. | |
1668 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
1669 pool_->CloseIdleSockets(); | |
1670 | |
1671 // Run the released socket wakeups. | |
1672 base::MessageLoop::current()->RunUntilIdle(); | |
1673 } | |
1674 | |
1675 TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) { | |
1676 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1677 | |
1678 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1679 ClientSocketHandle handle; | |
1680 TestCompletionCallback callback; | |
1681 CapturingBoundNetLog log; | |
1682 int rv = handle.Init("a", | |
1683 params_, | |
1684 LOWEST, | |
1685 callback.callback(), | |
1686 pool_.get(), | |
1687 log.bound()); | |
1688 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1689 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
1690 TestLoadTimingInfoNotConnected(handle); | |
1691 | |
1692 EXPECT_EQ(OK, callback.WaitForResult()); | |
1693 EXPECT_TRUE(handle.is_initialized()); | |
1694 EXPECT_TRUE(handle.socket()); | |
1695 TestLoadTimingInfoConnectedNotReused(handle); | |
1696 | |
1697 handle.Reset(); | |
1698 TestLoadTimingInfoNotConnected(handle); | |
1699 | |
1700 CapturingNetLog::CapturedEntryList entries; | |
1701 log.GetEntries(&entries); | |
1702 | |
1703 EXPECT_EQ(4u, entries.size()); | |
1704 EXPECT_TRUE(LogContainsBeginEvent( | |
1705 entries, 0, NetLog::TYPE_SOCKET_POOL)); | |
1706 EXPECT_TRUE(LogContainsEvent( | |
1707 entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB, | |
1708 NetLog::PHASE_NONE)); | |
1709 EXPECT_TRUE(LogContainsEvent( | |
1710 entries, 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, | |
1711 NetLog::PHASE_NONE)); | |
1712 EXPECT_TRUE(LogContainsEndEvent( | |
1713 entries, 3, NetLog::TYPE_SOCKET_POOL)); | |
1714 } | |
1715 | |
1716 TEST_F(ClientSocketPoolBaseTest, | |
1717 InitConnectionAsynchronousFailure) { | |
1718 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1719 | |
1720 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | |
1721 ClientSocketHandle handle; | |
1722 TestCompletionCallback callback; | |
1723 CapturingBoundNetLog log; | |
1724 // Set the additional error state members to ensure that they get cleared. | |
1725 handle.set_is_ssl_error(true); | |
1726 HttpResponseInfo info; | |
1727 info.headers = new HttpResponseHeaders(std::string()); | |
1728 handle.set_ssl_error_response_info(info); | |
1729 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
1730 params_, | |
1731 DEFAULT_PRIORITY, | |
1732 callback.callback(), | |
1733 pool_.get(), | |
1734 log.bound())); | |
1735 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
1736 EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
1737 EXPECT_FALSE(handle.is_ssl_error()); | |
1738 EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL); | |
1739 | |
1740 CapturingNetLog::CapturedEntryList entries; | |
1741 log.GetEntries(&entries); | |
1742 | |
1743 EXPECT_EQ(3u, entries.size()); | |
1744 EXPECT_TRUE(LogContainsBeginEvent( | |
1745 entries, 0, NetLog::TYPE_SOCKET_POOL)); | |
1746 EXPECT_TRUE(LogContainsEvent( | |
1747 entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB, | |
1748 NetLog::PHASE_NONE)); | |
1749 EXPECT_TRUE(LogContainsEndEvent( | |
1750 entries, 2, NetLog::TYPE_SOCKET_POOL)); | |
1751 } | |
1752 | |
1753 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { | |
1754 // TODO(eroman): Add back the log expectations! Removed them because the | |
1755 // ordering is difficult, and some may fire during destructor. | |
1756 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1757 | |
1758 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1759 ClientSocketHandle handle; | |
1760 TestCompletionCallback callback; | |
1761 ClientSocketHandle handle2; | |
1762 TestCompletionCallback callback2; | |
1763 | |
1764 EXPECT_EQ(ERR_IO_PENDING, | |
1765 handle.Init("a", | |
1766 params_, | |
1767 DEFAULT_PRIORITY, | |
1768 callback.callback(), | |
1769 pool_.get(), | |
1770 BoundNetLog())); | |
1771 CapturingBoundNetLog log2; | |
1772 EXPECT_EQ(ERR_IO_PENDING, | |
1773 handle2.Init("a", | |
1774 params_, | |
1775 DEFAULT_PRIORITY, | |
1776 callback2.callback(), | |
1777 pool_.get(), | |
1778 BoundNetLog())); | |
1779 | |
1780 handle.Reset(); | |
1781 | |
1782 | |
1783 // At this point, request 2 is just waiting for the connect job to finish. | |
1784 | |
1785 EXPECT_EQ(OK, callback2.WaitForResult()); | |
1786 handle2.Reset(); | |
1787 | |
1788 // Now request 2 has actually finished. | |
1789 // TODO(eroman): Add back log expectations. | |
1790 } | |
1791 | |
1792 TEST_F(ClientSocketPoolBaseTest, CancelRequestLimitsJobs) { | |
1793 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1794 | |
1795 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1796 | |
1797 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST)); | |
1798 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW)); | |
1799 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM)); | |
1800 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST)); | |
1801 | |
1802 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a")); | |
1803 (*requests())[2]->handle()->Reset(); | |
1804 (*requests())[3]->handle()->Reset(); | |
1805 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a")); | |
1806 | |
1807 (*requests())[1]->handle()->Reset(); | |
1808 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a")); | |
1809 | |
1810 (*requests())[0]->handle()->Reset(); | |
1811 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a")); | |
1812 } | |
1813 | |
1814 // When requests and ConnectJobs are not coupled, the request will get serviced | |
1815 // by whatever comes first. | |
1816 TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) { | |
1817 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1818 | |
1819 // Start job 1 (async OK) | |
1820 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
1821 | |
1822 std::vector<TestSocketRequest*> request_order; | |
1823 size_t completion_count; // unused | |
1824 TestSocketRequest req1(&request_order, &completion_count); | |
1825 int rv = req1.handle()->Init("a", | |
1826 params_, | |
1827 DEFAULT_PRIORITY, | |
1828 req1.callback(), pool_.get(), | |
1829 BoundNetLog()); | |
1830 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1831 EXPECT_EQ(OK, req1.WaitForResult()); | |
1832 | |
1833 // Job 1 finished OK. Start job 2 (also async OK). Request 3 is pending | |
1834 // without a job. | |
1835 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
1836 | |
1837 TestSocketRequest req2(&request_order, &completion_count); | |
1838 rv = req2.handle()->Init("a", | |
1839 params_, | |
1840 DEFAULT_PRIORITY, | |
1841 req2.callback(), | |
1842 pool_.get(), | |
1843 BoundNetLog()); | |
1844 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1845 TestSocketRequest req3(&request_order, &completion_count); | |
1846 rv = req3.handle()->Init("a", | |
1847 params_, | |
1848 DEFAULT_PRIORITY, | |
1849 req3.callback(), | |
1850 pool_.get(), | |
1851 BoundNetLog()); | |
1852 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1853 | |
1854 // Both Requests 2 and 3 are pending. We release socket 1 which should | |
1855 // service request 2. Request 3 should still be waiting. | |
1856 req1.handle()->Reset(); | |
1857 // Run the released socket wakeups. | |
1858 base::MessageLoop::current()->RunUntilIdle(); | |
1859 ASSERT_TRUE(req2.handle()->socket()); | |
1860 EXPECT_EQ(OK, req2.WaitForResult()); | |
1861 EXPECT_FALSE(req3.handle()->socket()); | |
1862 | |
1863 // Signal job 2, which should service request 3. | |
1864 | |
1865 client_socket_factory_.SignalJobs(); | |
1866 EXPECT_EQ(OK, req3.WaitForResult()); | |
1867 | |
1868 ASSERT_EQ(3U, request_order.size()); | |
1869 EXPECT_EQ(&req1, request_order[0]); | |
1870 EXPECT_EQ(&req2, request_order[1]); | |
1871 EXPECT_EQ(&req3, request_order[2]); | |
1872 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
1873 } | |
1874 | |
1875 // The requests are not coupled to the jobs. So, the requests should finish in | |
1876 // their priority / insertion order. | |
1877 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { | |
1878 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1879 // First two jobs are async. | |
1880 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | |
1881 | |
1882 std::vector<TestSocketRequest*> request_order; | |
1883 size_t completion_count; // unused | |
1884 TestSocketRequest req1(&request_order, &completion_count); | |
1885 int rv = req1.handle()->Init("a", | |
1886 params_, | |
1887 DEFAULT_PRIORITY, | |
1888 req1.callback(), | |
1889 pool_.get(), | |
1890 BoundNetLog()); | |
1891 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1892 | |
1893 TestSocketRequest req2(&request_order, &completion_count); | |
1894 rv = req2.handle()->Init("a", | |
1895 params_, | |
1896 DEFAULT_PRIORITY, | |
1897 req2.callback(), | |
1898 pool_.get(), | |
1899 BoundNetLog()); | |
1900 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1901 | |
1902 // The pending job is sync. | |
1903 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
1904 | |
1905 TestSocketRequest req3(&request_order, &completion_count); | |
1906 rv = req3.handle()->Init("a", | |
1907 params_, | |
1908 DEFAULT_PRIORITY, | |
1909 req3.callback(), | |
1910 pool_.get(), | |
1911 BoundNetLog()); | |
1912 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1913 | |
1914 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); | |
1915 EXPECT_EQ(OK, req2.WaitForResult()); | |
1916 EXPECT_EQ(ERR_CONNECTION_FAILED, req3.WaitForResult()); | |
1917 | |
1918 ASSERT_EQ(3U, request_order.size()); | |
1919 EXPECT_EQ(&req1, request_order[0]); | |
1920 EXPECT_EQ(&req2, request_order[1]); | |
1921 EXPECT_EQ(&req3, request_order[2]); | |
1922 } | |
1923 | |
1924 // Test GetLoadState in the case there's only one socket request. | |
1925 TEST_F(ClientSocketPoolBaseTest, LoadStateOneRequest) { | |
1926 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
1927 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
1928 | |
1929 ClientSocketHandle handle; | |
1930 TestCompletionCallback callback; | |
1931 int rv = handle.Init("a", | |
1932 params_, | |
1933 DEFAULT_PRIORITY, | |
1934 callback.callback(), | |
1935 pool_.get(), | |
1936 BoundNetLog()); | |
1937 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1938 EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); | |
1939 | |
1940 client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE); | |
1941 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle.GetLoadState()); | |
1942 | |
1943 // No point in completing the connection, since ClientSocketHandles only | |
1944 // expect the LoadState to be checked while connecting. | |
1945 } | |
1946 | |
1947 // Test GetLoadState in the case there are two socket requests. | |
1948 TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequests) { | |
1949 CreatePool(2, 2); | |
1950 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
1951 | |
1952 ClientSocketHandle handle; | |
1953 TestCompletionCallback callback; | |
1954 int rv = handle.Init("a", | |
1955 params_, | |
1956 DEFAULT_PRIORITY, | |
1957 callback.callback(), | |
1958 pool_.get(), | |
1959 BoundNetLog()); | |
1960 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1961 | |
1962 ClientSocketHandle handle2; | |
1963 TestCompletionCallback callback2; | |
1964 rv = handle2.Init("a", | |
1965 params_, | |
1966 DEFAULT_PRIORITY, | |
1967 callback2.callback(), | |
1968 pool_.get(), | |
1969 BoundNetLog()); | |
1970 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1971 | |
1972 // If the first Job is in an earlier state than the second, the state of | |
1973 // the second job should be used for both handles. | |
1974 client_socket_factory_.SetJobLoadState(0, LOAD_STATE_RESOLVING_HOST); | |
1975 EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); | |
1976 EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState()); | |
1977 | |
1978 // If the second Job is in an earlier state than the second, the state of | |
1979 // the first job should be used for both handles. | |
1980 client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE); | |
1981 // One request is farther | |
1982 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle.GetLoadState()); | |
1983 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle2.GetLoadState()); | |
1984 | |
1985 // Farthest along job connects and the first request gets the socket. The | |
1986 // second handle switches to the state of the remaining ConnectJob. | |
1987 client_socket_factory_.SignalJob(0); | |
1988 EXPECT_EQ(OK, callback.WaitForResult()); | |
1989 EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState()); | |
1990 } | |
1991 | |
1992 // Test GetLoadState in the case the per-group limit is reached. | |
1993 TEST_F(ClientSocketPoolBaseTest, LoadStateGroupLimit) { | |
1994 CreatePool(2, 1); | |
1995 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
1996 | |
1997 ClientSocketHandle handle; | |
1998 TestCompletionCallback callback; | |
1999 int rv = handle.Init("a", | |
2000 params_, | |
2001 MEDIUM, | |
2002 callback.callback(), | |
2003 pool_.get(), | |
2004 BoundNetLog()); | |
2005 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2006 EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); | |
2007 | |
2008 // Request another socket from the same pool, buth with a higher priority. | |
2009 // The first request should now be stalled at the socket group limit. | |
2010 ClientSocketHandle handle2; | |
2011 TestCompletionCallback callback2; | |
2012 rv = handle2.Init("a", | |
2013 params_, | |
2014 HIGHEST, | |
2015 callback2.callback(), | |
2016 pool_.get(), | |
2017 BoundNetLog()); | |
2018 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2019 EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState()); | |
2020 EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState()); | |
2021 | |
2022 // The first handle should remain stalled as the other socket goes through | |
2023 // the connect process. | |
2024 | |
2025 client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE); | |
2026 EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState()); | |
2027 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle2.GetLoadState()); | |
2028 | |
2029 client_socket_factory_.SignalJob(0); | |
2030 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2031 EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState()); | |
2032 | |
2033 // Closing the second socket should cause the stalled handle to finally get a | |
2034 // ConnectJob. | |
2035 handle2.socket()->Disconnect(); | |
2036 handle2.Reset(); | |
2037 EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); | |
2038 } | |
2039 | |
2040 // Test GetLoadState in the case the per-pool limit is reached. | |
2041 TEST_F(ClientSocketPoolBaseTest, LoadStatePoolLimit) { | |
2042 CreatePool(2, 2); | |
2043 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2044 | |
2045 ClientSocketHandle handle; | |
2046 TestCompletionCallback callback; | |
2047 int rv = handle.Init("a", | |
2048 params_, | |
2049 DEFAULT_PRIORITY, | |
2050 callback.callback(), | |
2051 pool_.get(), | |
2052 BoundNetLog()); | |
2053 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2054 | |
2055 // Request for socket from another pool. | |
2056 ClientSocketHandle handle2; | |
2057 TestCompletionCallback callback2; | |
2058 rv = handle2.Init("b", | |
2059 params_, | |
2060 DEFAULT_PRIORITY, | |
2061 callback2.callback(), | |
2062 pool_.get(), | |
2063 BoundNetLog()); | |
2064 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2065 | |
2066 // Request another socket from the first pool. Request should stall at the | |
2067 // socket pool limit. | |
2068 ClientSocketHandle handle3; | |
2069 TestCompletionCallback callback3; | |
2070 rv = handle3.Init("a", | |
2071 params_, | |
2072 DEFAULT_PRIORITY, | |
2073 callback2.callback(), | |
2074 pool_.get(), | |
2075 BoundNetLog()); | |
2076 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2077 | |
2078 // The third handle should remain stalled as the other sockets in its group | |
2079 // goes through the connect process. | |
2080 | |
2081 EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); | |
2082 EXPECT_EQ(LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL, handle3.GetLoadState()); | |
2083 | |
2084 client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE); | |
2085 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle.GetLoadState()); | |
2086 EXPECT_EQ(LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL, handle3.GetLoadState()); | |
2087 | |
2088 client_socket_factory_.SignalJob(0); | |
2089 EXPECT_EQ(OK, callback.WaitForResult()); | |
2090 EXPECT_EQ(LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL, handle3.GetLoadState()); | |
2091 | |
2092 // Closing a socket should allow the stalled handle to finally get a new | |
2093 // ConnectJob. | |
2094 handle.socket()->Disconnect(); | |
2095 handle.Reset(); | |
2096 EXPECT_EQ(LOAD_STATE_CONNECTING, handle3.GetLoadState()); | |
2097 } | |
2098 | |
2099 TEST_F(ClientSocketPoolBaseTest, Recoverable) { | |
2100 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2101 connect_job_factory_->set_job_type(TestConnectJob::kMockRecoverableJob); | |
2102 | |
2103 ClientSocketHandle handle; | |
2104 TestCompletionCallback callback; | |
2105 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, | |
2106 handle.Init("a", params_, DEFAULT_PRIORITY, callback.callback(), | |
2107 pool_.get(), BoundNetLog())); | |
2108 EXPECT_TRUE(handle.is_initialized()); | |
2109 EXPECT_TRUE(handle.socket()); | |
2110 } | |
2111 | |
2112 TEST_F(ClientSocketPoolBaseTest, AsyncRecoverable) { | |
2113 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2114 | |
2115 connect_job_factory_->set_job_type( | |
2116 TestConnectJob::kMockPendingRecoverableJob); | |
2117 ClientSocketHandle handle; | |
2118 TestCompletionCallback callback; | |
2119 EXPECT_EQ(ERR_IO_PENDING, | |
2120 handle.Init("a", | |
2121 params_, | |
2122 DEFAULT_PRIORITY, | |
2123 callback.callback(), | |
2124 pool_.get(), | |
2125 BoundNetLog())); | |
2126 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
2127 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback.WaitForResult()); | |
2128 EXPECT_TRUE(handle.is_initialized()); | |
2129 EXPECT_TRUE(handle.socket()); | |
2130 } | |
2131 | |
2132 TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateSynchronous) { | |
2133 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2134 connect_job_factory_->set_job_type( | |
2135 TestConnectJob::kMockAdditionalErrorStateJob); | |
2136 | |
2137 ClientSocketHandle handle; | |
2138 TestCompletionCallback callback; | |
2139 EXPECT_EQ(ERR_CONNECTION_FAILED, | |
2140 handle.Init("a", | |
2141 params_, | |
2142 DEFAULT_PRIORITY, | |
2143 callback.callback(), | |
2144 pool_.get(), | |
2145 BoundNetLog())); | |
2146 EXPECT_FALSE(handle.is_initialized()); | |
2147 EXPECT_FALSE(handle.socket()); | |
2148 EXPECT_TRUE(handle.is_ssl_error()); | |
2149 EXPECT_FALSE(handle.ssl_error_response_info().headers.get() == NULL); | |
2150 } | |
2151 | |
2152 TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateAsynchronous) { | |
2153 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2154 | |
2155 connect_job_factory_->set_job_type( | |
2156 TestConnectJob::kMockPendingAdditionalErrorStateJob); | |
2157 ClientSocketHandle handle; | |
2158 TestCompletionCallback callback; | |
2159 EXPECT_EQ(ERR_IO_PENDING, | |
2160 handle.Init("a", | |
2161 params_, | |
2162 DEFAULT_PRIORITY, | |
2163 callback.callback(), | |
2164 pool_.get(), | |
2165 BoundNetLog())); | |
2166 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
2167 EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
2168 EXPECT_FALSE(handle.is_initialized()); | |
2169 EXPECT_FALSE(handle.socket()); | |
2170 EXPECT_TRUE(handle.is_ssl_error()); | |
2171 EXPECT_FALSE(handle.ssl_error_response_info().headers.get() == NULL); | |
2172 } | |
2173 | |
2174 // Make sure we can reuse sockets when the cleanup timer is disabled. | |
2175 TEST_F(ClientSocketPoolBaseTest, DisableCleanupTimerReuse) { | |
2176 // Disable cleanup timer. | |
2177 internal::ClientSocketPoolBaseHelper::set_cleanup_timer_enabled(false); | |
2178 | |
2179 CreatePoolWithIdleTimeouts( | |
2180 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup, | |
2181 base::TimeDelta(), // Time out unused sockets immediately. | |
2182 base::TimeDelta::FromDays(1)); // Don't time out used sockets. | |
2183 | |
2184 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2185 | |
2186 ClientSocketHandle handle; | |
2187 TestCompletionCallback callback; | |
2188 int rv = handle.Init("a", | |
2189 params_, | |
2190 LOWEST, | |
2191 callback.callback(), | |
2192 pool_.get(), | |
2193 BoundNetLog()); | |
2194 ASSERT_EQ(ERR_IO_PENDING, rv); | |
2195 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
2196 ASSERT_EQ(OK, callback.WaitForResult()); | |
2197 | |
2198 // Use and release the socket. | |
2199 EXPECT_EQ(1, handle.socket()->Write(NULL, 1, CompletionCallback())); | |
2200 TestLoadTimingInfoConnectedNotReused(handle); | |
2201 handle.Reset(); | |
2202 | |
2203 // Should now have one idle socket. | |
2204 ASSERT_EQ(1, pool_->IdleSocketCount()); | |
2205 | |
2206 // Request a new socket. This should reuse the old socket and complete | |
2207 // synchronously. | |
2208 CapturingBoundNetLog log; | |
2209 rv = handle.Init("a", | |
2210 params_, | |
2211 LOWEST, | |
2212 CompletionCallback(), | |
2213 pool_.get(), | |
2214 log.bound()); | |
2215 ASSERT_EQ(OK, rv); | |
2216 EXPECT_TRUE(handle.is_reused()); | |
2217 TestLoadTimingInfoConnectedReused(handle); | |
2218 | |
2219 ASSERT_TRUE(pool_->HasGroup("a")); | |
2220 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
2221 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | |
2222 | |
2223 CapturingNetLog::CapturedEntryList entries; | |
2224 log.GetEntries(&entries); | |
2225 EXPECT_TRUE(LogContainsEntryWithType( | |
2226 entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET)); | |
2227 } | |
2228 | |
2229 // Make sure we cleanup old unused sockets when the cleanup timer is disabled. | |
2230 TEST_F(ClientSocketPoolBaseTest, DisableCleanupTimerNoReuse) { | |
2231 // Disable cleanup timer. | |
2232 internal::ClientSocketPoolBaseHelper::set_cleanup_timer_enabled(false); | |
2233 | |
2234 CreatePoolWithIdleTimeouts( | |
2235 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup, | |
2236 base::TimeDelta(), // Time out unused sockets immediately | |
2237 base::TimeDelta()); // Time out used sockets immediately | |
2238 | |
2239 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2240 | |
2241 // Startup two mock pending connect jobs, which will sit in the MessageLoop. | |
2242 | |
2243 ClientSocketHandle handle; | |
2244 TestCompletionCallback callback; | |
2245 int rv = handle.Init("a", | |
2246 params_, | |
2247 LOWEST, | |
2248 callback.callback(), | |
2249 pool_.get(), | |
2250 BoundNetLog()); | |
2251 ASSERT_EQ(ERR_IO_PENDING, rv); | |
2252 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
2253 | |
2254 ClientSocketHandle handle2; | |
2255 TestCompletionCallback callback2; | |
2256 rv = handle2.Init("a", | |
2257 params_, | |
2258 LOWEST, | |
2259 callback2.callback(), | |
2260 pool_.get(), | |
2261 BoundNetLog()); | |
2262 ASSERT_EQ(ERR_IO_PENDING, rv); | |
2263 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle2)); | |
2264 | |
2265 // Cancel one of the requests. Wait for the other, which will get the first | |
2266 // job. Release the socket. Run the loop again to make sure the second | |
2267 // socket is sitting idle and the first one is released (since ReleaseSocket() | |
2268 // just posts a DoReleaseSocket() task). | |
2269 | |
2270 handle.Reset(); | |
2271 ASSERT_EQ(OK, callback2.WaitForResult()); | |
2272 // Use the socket. | |
2273 EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); | |
2274 handle2.Reset(); | |
2275 | |
2276 // We post all of our delayed tasks with a 2ms delay. I.e. they don't | |
2277 // actually become pending until 2ms after they have been created. In order | |
2278 // to flush all tasks, we need to wait so that we know there are no | |
2279 // soon-to-be-pending tasks waiting. | |
2280 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | |
2281 base::MessageLoop::current()->RunUntilIdle(); | |
2282 | |
2283 // Both sockets should now be idle. | |
2284 ASSERT_EQ(2, pool_->IdleSocketCount()); | |
2285 | |
2286 // Request a new socket. This should cleanup the unused and timed out ones. | |
2287 // A new socket will be created rather than reusing the idle one. | |
2288 CapturingBoundNetLog log; | |
2289 TestCompletionCallback callback3; | |
2290 rv = handle.Init("a", | |
2291 params_, | |
2292 LOWEST, | |
2293 callback3.callback(), | |
2294 pool_.get(), | |
2295 log.bound()); | |
2296 ASSERT_EQ(ERR_IO_PENDING, rv); | |
2297 ASSERT_EQ(OK, callback3.WaitForResult()); | |
2298 EXPECT_FALSE(handle.is_reused()); | |
2299 | |
2300 // Make sure the idle socket is closed. | |
2301 ASSERT_TRUE(pool_->HasGroup("a")); | |
2302 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
2303 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | |
2304 | |
2305 CapturingNetLog::CapturedEntryList entries; | |
2306 log.GetEntries(&entries); | |
2307 EXPECT_FALSE(LogContainsEntryWithType( | |
2308 entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET)); | |
2309 } | |
2310 | |
2311 TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) { | |
2312 CreatePoolWithIdleTimeouts( | |
2313 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup, | |
2314 base::TimeDelta(), // Time out unused sockets immediately. | |
2315 base::TimeDelta::FromDays(1)); // Don't time out used sockets. | |
2316 | |
2317 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2318 | |
2319 // Startup two mock pending connect jobs, which will sit in the MessageLoop. | |
2320 | |
2321 ClientSocketHandle handle; | |
2322 TestCompletionCallback callback; | |
2323 int rv = handle.Init("a", | |
2324 params_, | |
2325 LOWEST, | |
2326 callback.callback(), | |
2327 pool_.get(), | |
2328 BoundNetLog()); | |
2329 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2330 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); | |
2331 | |
2332 ClientSocketHandle handle2; | |
2333 TestCompletionCallback callback2; | |
2334 rv = handle2.Init("a", | |
2335 params_, | |
2336 LOWEST, | |
2337 callback2.callback(), | |
2338 pool_.get(), | |
2339 BoundNetLog()); | |
2340 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2341 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle2)); | |
2342 | |
2343 // Cancel one of the requests. Wait for the other, which will get the first | |
2344 // job. Release the socket. Run the loop again to make sure the second | |
2345 // socket is sitting idle and the first one is released (since ReleaseSocket() | |
2346 // just posts a DoReleaseSocket() task). | |
2347 | |
2348 handle.Reset(); | |
2349 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2350 // Use the socket. | |
2351 EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); | |
2352 handle2.Reset(); | |
2353 | |
2354 // We post all of our delayed tasks with a 2ms delay. I.e. they don't | |
2355 // actually become pending until 2ms after they have been created. In order | |
2356 // to flush all tasks, we need to wait so that we know there are no | |
2357 // soon-to-be-pending tasks waiting. | |
2358 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | |
2359 base::MessageLoop::current()->RunUntilIdle(); | |
2360 | |
2361 ASSERT_EQ(2, pool_->IdleSocketCount()); | |
2362 | |
2363 // Invoke the idle socket cleanup check. Only one socket should be left, the | |
2364 // used socket. Request it to make sure that it's used. | |
2365 | |
2366 pool_->CleanupTimedOutIdleSockets(); | |
2367 CapturingBoundNetLog log; | |
2368 rv = handle.Init("a", | |
2369 params_, | |
2370 LOWEST, | |
2371 callback.callback(), | |
2372 pool_.get(), | |
2373 log.bound()); | |
2374 EXPECT_EQ(OK, rv); | |
2375 EXPECT_TRUE(handle.is_reused()); | |
2376 | |
2377 CapturingNetLog::CapturedEntryList entries; | |
2378 log.GetEntries(&entries); | |
2379 EXPECT_TRUE(LogContainsEntryWithType( | |
2380 entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET)); | |
2381 } | |
2382 | |
2383 // Make sure that we process all pending requests even when we're stalling | |
2384 // because of multiple releasing disconnected sockets. | |
2385 TEST_F(ClientSocketPoolBaseTest, MultipleReleasingDisconnectedSockets) { | |
2386 CreatePoolWithIdleTimeouts( | |
2387 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup, | |
2388 base::TimeDelta(), // Time out unused sockets immediately. | |
2389 base::TimeDelta::FromDays(1)); // Don't time out used sockets. | |
2390 | |
2391 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
2392 | |
2393 // Startup 4 connect jobs. Two of them will be pending. | |
2394 | |
2395 ClientSocketHandle handle; | |
2396 TestCompletionCallback callback; | |
2397 int rv = handle.Init("a", | |
2398 params_, | |
2399 LOWEST, | |
2400 callback.callback(), | |
2401 pool_.get(), | |
2402 BoundNetLog()); | |
2403 EXPECT_EQ(OK, rv); | |
2404 | |
2405 ClientSocketHandle handle2; | |
2406 TestCompletionCallback callback2; | |
2407 rv = handle2.Init("a", | |
2408 params_, | |
2409 LOWEST, | |
2410 callback2.callback(), | |
2411 pool_.get(), | |
2412 BoundNetLog()); | |
2413 EXPECT_EQ(OK, rv); | |
2414 | |
2415 ClientSocketHandle handle3; | |
2416 TestCompletionCallback callback3; | |
2417 rv = handle3.Init("a", | |
2418 params_, | |
2419 LOWEST, | |
2420 callback3.callback(), | |
2421 pool_.get(), | |
2422 BoundNetLog()); | |
2423 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2424 | |
2425 ClientSocketHandle handle4; | |
2426 TestCompletionCallback callback4; | |
2427 rv = handle4.Init("a", | |
2428 params_, | |
2429 LOWEST, | |
2430 callback4.callback(), | |
2431 pool_.get(), | |
2432 BoundNetLog()); | |
2433 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2434 | |
2435 // Release two disconnected sockets. | |
2436 | |
2437 handle.socket()->Disconnect(); | |
2438 handle.Reset(); | |
2439 handle2.socket()->Disconnect(); | |
2440 handle2.Reset(); | |
2441 | |
2442 EXPECT_EQ(OK, callback3.WaitForResult()); | |
2443 EXPECT_FALSE(handle3.is_reused()); | |
2444 EXPECT_EQ(OK, callback4.WaitForResult()); | |
2445 EXPECT_FALSE(handle4.is_reused()); | |
2446 } | |
2447 | |
2448 // Regression test for http://crbug.com/42267. | |
2449 // When DoReleaseSocket() is processed for one socket, it is blocked because the | |
2450 // other stalled groups all have releasing sockets, so no progress can be made. | |
2451 TEST_F(ClientSocketPoolBaseTest, SocketLimitReleasingSockets) { | |
2452 CreatePoolWithIdleTimeouts( | |
2453 4 /* socket limit */, 4 /* socket limit per group */, | |
2454 base::TimeDelta(), // Time out unused sockets immediately. | |
2455 base::TimeDelta::FromDays(1)); // Don't time out used sockets. | |
2456 | |
2457 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
2458 | |
2459 // Max out the socket limit with 2 per group. | |
2460 | |
2461 ClientSocketHandle handle_a[4]; | |
2462 TestCompletionCallback callback_a[4]; | |
2463 ClientSocketHandle handle_b[4]; | |
2464 TestCompletionCallback callback_b[4]; | |
2465 | |
2466 for (int i = 0; i < 2; ++i) { | |
2467 EXPECT_EQ(OK, handle_a[i].Init("a", | |
2468 params_, | |
2469 LOWEST, | |
2470 callback_a[i].callback(), | |
2471 pool_.get(), | |
2472 BoundNetLog())); | |
2473 EXPECT_EQ(OK, handle_b[i].Init("b", | |
2474 params_, | |
2475 LOWEST, | |
2476 callback_b[i].callback(), | |
2477 pool_.get(), | |
2478 BoundNetLog())); | |
2479 } | |
2480 | |
2481 // Make 4 pending requests, 2 per group. | |
2482 | |
2483 for (int i = 2; i < 4; ++i) { | |
2484 EXPECT_EQ(ERR_IO_PENDING, | |
2485 handle_a[i].Init("a", | |
2486 params_, | |
2487 LOWEST, | |
2488 callback_a[i].callback(), | |
2489 pool_.get(), | |
2490 BoundNetLog())); | |
2491 EXPECT_EQ(ERR_IO_PENDING, | |
2492 handle_b[i].Init("b", | |
2493 params_, | |
2494 LOWEST, | |
2495 callback_b[i].callback(), | |
2496 pool_.get(), | |
2497 BoundNetLog())); | |
2498 } | |
2499 | |
2500 // Release b's socket first. The order is important, because in | |
2501 // DoReleaseSocket(), we'll process b's released socket, and since both b and | |
2502 // a are stalled, but 'a' is lower lexicographically, we'll process group 'a' | |
2503 // first, which has a releasing socket, so it refuses to start up another | |
2504 // ConnectJob. So, we used to infinite loop on this. | |
2505 handle_b[0].socket()->Disconnect(); | |
2506 handle_b[0].Reset(); | |
2507 handle_a[0].socket()->Disconnect(); | |
2508 handle_a[0].Reset(); | |
2509 | |
2510 // Used to get stuck here. | |
2511 base::MessageLoop::current()->RunUntilIdle(); | |
2512 | |
2513 handle_b[1].socket()->Disconnect(); | |
2514 handle_b[1].Reset(); | |
2515 handle_a[1].socket()->Disconnect(); | |
2516 handle_a[1].Reset(); | |
2517 | |
2518 for (int i = 2; i < 4; ++i) { | |
2519 EXPECT_EQ(OK, callback_b[i].WaitForResult()); | |
2520 EXPECT_EQ(OK, callback_a[i].WaitForResult()); | |
2521 } | |
2522 } | |
2523 | |
2524 TEST_F(ClientSocketPoolBaseTest, | |
2525 ReleasingDisconnectedSocketsMaintainsPriorityOrder) { | |
2526 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2527 | |
2528 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2529 | |
2530 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
2531 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
2532 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
2533 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | |
2534 | |
2535 EXPECT_EQ(OK, (*requests())[0]->WaitForResult()); | |
2536 EXPECT_EQ(OK, (*requests())[1]->WaitForResult()); | |
2537 EXPECT_EQ(2u, completion_count()); | |
2538 | |
2539 // Releases one connection. | |
2540 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE)); | |
2541 EXPECT_EQ(OK, (*requests())[2]->WaitForResult()); | |
2542 | |
2543 EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE)); | |
2544 EXPECT_EQ(OK, (*requests())[3]->WaitForResult()); | |
2545 EXPECT_EQ(4u, completion_count()); | |
2546 | |
2547 EXPECT_EQ(1, GetOrderOfRequest(1)); | |
2548 EXPECT_EQ(2, GetOrderOfRequest(2)); | |
2549 EXPECT_EQ(3, GetOrderOfRequest(3)); | |
2550 EXPECT_EQ(4, GetOrderOfRequest(4)); | |
2551 | |
2552 // Make sure we test order of all requests made. | |
2553 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(5)); | |
2554 } | |
2555 | |
2556 class TestReleasingSocketRequest : public TestCompletionCallbackBase { | |
2557 public: | |
2558 TestReleasingSocketRequest(TestClientSocketPool* pool, | |
2559 int expected_result, | |
2560 bool reset_releasing_handle) | |
2561 : pool_(pool), | |
2562 expected_result_(expected_result), | |
2563 reset_releasing_handle_(reset_releasing_handle), | |
2564 callback_(base::Bind(&TestReleasingSocketRequest::OnComplete, | |
2565 base::Unretained(this))) { | |
2566 } | |
2567 | |
2568 ~TestReleasingSocketRequest() override {} | |
2569 | |
2570 ClientSocketHandle* handle() { return &handle_; } | |
2571 | |
2572 const CompletionCallback& callback() const { return callback_; } | |
2573 | |
2574 private: | |
2575 void OnComplete(int result) { | |
2576 SetResult(result); | |
2577 if (reset_releasing_handle_) | |
2578 handle_.Reset(); | |
2579 | |
2580 scoped_refptr<TestSocketParams> con_params( | |
2581 new TestSocketParams(false /* ignore_limits */)); | |
2582 EXPECT_EQ(expected_result_, | |
2583 handle2_.Init("a", con_params, DEFAULT_PRIORITY, | |
2584 callback2_.callback(), pool_, BoundNetLog())); | |
2585 } | |
2586 | |
2587 TestClientSocketPool* const pool_; | |
2588 int expected_result_; | |
2589 bool reset_releasing_handle_; | |
2590 ClientSocketHandle handle_; | |
2591 ClientSocketHandle handle2_; | |
2592 CompletionCallback callback_; | |
2593 TestCompletionCallback callback2_; | |
2594 }; | |
2595 | |
2596 | |
2597 TEST_F(ClientSocketPoolBaseTest, AdditionalErrorSocketsDontUseSlot) { | |
2598 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2599 | |
2600 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
2601 EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY)); | |
2602 EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY)); | |
2603 | |
2604 EXPECT_EQ(static_cast<int>(requests_size()), | |
2605 client_socket_factory_.allocation_count()); | |
2606 | |
2607 connect_job_factory_->set_job_type( | |
2608 TestConnectJob::kMockPendingAdditionalErrorStateJob); | |
2609 TestReleasingSocketRequest req(pool_.get(), OK, false); | |
2610 EXPECT_EQ(ERR_IO_PENDING, | |
2611 req.handle()->Init("a", params_, DEFAULT_PRIORITY, req.callback(), | |
2612 pool_.get(), BoundNetLog())); | |
2613 // The next job should complete synchronously | |
2614 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
2615 | |
2616 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); | |
2617 EXPECT_FALSE(req.handle()->is_initialized()); | |
2618 EXPECT_FALSE(req.handle()->socket()); | |
2619 EXPECT_TRUE(req.handle()->is_ssl_error()); | |
2620 EXPECT_FALSE(req.handle()->ssl_error_response_info().headers.get() == NULL); | |
2621 } | |
2622 | |
2623 // http://crbug.com/44724 regression test. | |
2624 // We start releasing the pool when we flush on network change. When that | |
2625 // happens, the only active references are in the ClientSocketHandles. When a | |
2626 // ConnectJob completes and calls back into the last ClientSocketHandle, that | |
2627 // callback can release the last reference and delete the pool. After the | |
2628 // callback finishes, we go back to the stack frame within the now-deleted pool. | |
2629 // Executing any code that refers to members of the now-deleted pool can cause | |
2630 // crashes. | |
2631 TEST_F(ClientSocketPoolBaseTest, CallbackThatReleasesPool) { | |
2632 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2633 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | |
2634 | |
2635 ClientSocketHandle handle; | |
2636 TestCompletionCallback callback; | |
2637 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
2638 params_, | |
2639 DEFAULT_PRIORITY, | |
2640 callback.callback(), | |
2641 pool_.get(), | |
2642 BoundNetLog())); | |
2643 | |
2644 pool_->FlushWithError(ERR_NETWORK_CHANGED); | |
2645 | |
2646 // We'll call back into this now. | |
2647 callback.WaitForResult(); | |
2648 } | |
2649 | |
2650 TEST_F(ClientSocketPoolBaseTest, DoNotReuseSocketAfterFlush) { | |
2651 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2652 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2653 | |
2654 ClientSocketHandle handle; | |
2655 TestCompletionCallback callback; | |
2656 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
2657 params_, | |
2658 DEFAULT_PRIORITY, | |
2659 callback.callback(), | |
2660 pool_.get(), | |
2661 BoundNetLog())); | |
2662 EXPECT_EQ(OK, callback.WaitForResult()); | |
2663 EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type()); | |
2664 | |
2665 pool_->FlushWithError(ERR_NETWORK_CHANGED); | |
2666 | |
2667 handle.Reset(); | |
2668 base::MessageLoop::current()->RunUntilIdle(); | |
2669 | |
2670 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
2671 params_, | |
2672 DEFAULT_PRIORITY, | |
2673 callback.callback(), | |
2674 pool_.get(), | |
2675 BoundNetLog())); | |
2676 EXPECT_EQ(OK, callback.WaitForResult()); | |
2677 EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type()); | |
2678 } | |
2679 | |
2680 class ConnectWithinCallback : public TestCompletionCallbackBase { | |
2681 public: | |
2682 ConnectWithinCallback( | |
2683 const std::string& group_name, | |
2684 const scoped_refptr<TestSocketParams>& params, | |
2685 TestClientSocketPool* pool) | |
2686 : group_name_(group_name), | |
2687 params_(params), | |
2688 pool_(pool), | |
2689 callback_(base::Bind(&ConnectWithinCallback::OnComplete, | |
2690 base::Unretained(this))) { | |
2691 } | |
2692 | |
2693 ~ConnectWithinCallback() override {} | |
2694 | |
2695 int WaitForNestedResult() { | |
2696 return nested_callback_.WaitForResult(); | |
2697 } | |
2698 | |
2699 const CompletionCallback& callback() const { return callback_; } | |
2700 | |
2701 private: | |
2702 void OnComplete(int result) { | |
2703 SetResult(result); | |
2704 EXPECT_EQ(ERR_IO_PENDING, | |
2705 handle_.Init(group_name_, | |
2706 params_, | |
2707 DEFAULT_PRIORITY, | |
2708 nested_callback_.callback(), | |
2709 pool_, | |
2710 BoundNetLog())); | |
2711 } | |
2712 | |
2713 const std::string group_name_; | |
2714 const scoped_refptr<TestSocketParams> params_; | |
2715 TestClientSocketPool* const pool_; | |
2716 ClientSocketHandle handle_; | |
2717 CompletionCallback callback_; | |
2718 TestCompletionCallback nested_callback_; | |
2719 | |
2720 DISALLOW_COPY_AND_ASSIGN(ConnectWithinCallback); | |
2721 }; | |
2722 | |
2723 TEST_F(ClientSocketPoolBaseTest, AbortAllRequestsOnFlush) { | |
2724 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2725 | |
2726 // First job will be waiting until it gets aborted. | |
2727 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2728 | |
2729 ClientSocketHandle handle; | |
2730 ConnectWithinCallback callback("a", params_, pool_.get()); | |
2731 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
2732 params_, | |
2733 DEFAULT_PRIORITY, | |
2734 callback.callback(), | |
2735 pool_.get(), | |
2736 BoundNetLog())); | |
2737 | |
2738 // Second job will be started during the first callback, and will | |
2739 // asynchronously complete with OK. | |
2740 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2741 pool_->FlushWithError(ERR_NETWORK_CHANGED); | |
2742 EXPECT_EQ(ERR_NETWORK_CHANGED, callback.WaitForResult()); | |
2743 EXPECT_EQ(OK, callback.WaitForNestedResult()); | |
2744 } | |
2745 | |
2746 // Cancel a pending socket request while we're at max sockets, | |
2747 // and verify that the backup socket firing doesn't cause a crash. | |
2748 TEST_F(ClientSocketPoolBaseTest, BackupSocketCancelAtMaxSockets) { | |
2749 // Max 4 sockets globally, max 4 sockets per group. | |
2750 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
2751 pool_->EnableConnectBackupJobs(); | |
2752 | |
2753 // Create the first socket and set to ERR_IO_PENDING. This starts the backup | |
2754 // timer. | |
2755 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2756 ClientSocketHandle handle; | |
2757 TestCompletionCallback callback; | |
2758 EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar", | |
2759 params_, | |
2760 DEFAULT_PRIORITY, | |
2761 callback.callback(), | |
2762 pool_.get(), | |
2763 BoundNetLog())); | |
2764 | |
2765 // Start (MaxSockets - 1) connected sockets to reach max sockets. | |
2766 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
2767 ClientSocketHandle handles[kDefaultMaxSockets]; | |
2768 for (int i = 1; i < kDefaultMaxSockets; ++i) { | |
2769 TestCompletionCallback callback; | |
2770 EXPECT_EQ(OK, handles[i].Init("bar", | |
2771 params_, | |
2772 DEFAULT_PRIORITY, | |
2773 callback.callback(), | |
2774 pool_.get(), | |
2775 BoundNetLog())); | |
2776 } | |
2777 | |
2778 base::MessageLoop::current()->RunUntilIdle(); | |
2779 | |
2780 // Cancel the pending request. | |
2781 handle.Reset(); | |
2782 | |
2783 // Wait for the backup timer to fire (add some slop to ensure it fires) | |
2784 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( | |
2785 ClientSocketPool::kMaxConnectRetryIntervalMs / 2 * 3)); | |
2786 | |
2787 base::MessageLoop::current()->RunUntilIdle(); | |
2788 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | |
2789 } | |
2790 | |
2791 TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterCancelingAllRequests) { | |
2792 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
2793 pool_->EnableConnectBackupJobs(); | |
2794 | |
2795 // Create the first socket and set to ERR_IO_PENDING. This starts the backup | |
2796 // timer. | |
2797 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2798 ClientSocketHandle handle; | |
2799 TestCompletionCallback callback; | |
2800 EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar", | |
2801 params_, | |
2802 DEFAULT_PRIORITY, | |
2803 callback.callback(), | |
2804 pool_.get(), | |
2805 BoundNetLog())); | |
2806 ASSERT_TRUE(pool_->HasGroup("bar")); | |
2807 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("bar")); | |
2808 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("bar")); | |
2809 | |
2810 // Cancel the socket request. This should cancel the backup timer. Wait for | |
2811 // the backup time to see if it indeed got canceled. | |
2812 handle.Reset(); | |
2813 // Wait for the backup timer to fire (add some slop to ensure it fires) | |
2814 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( | |
2815 ClientSocketPool::kMaxConnectRetryIntervalMs / 2 * 3)); | |
2816 base::MessageLoop::current()->RunUntilIdle(); | |
2817 ASSERT_TRUE(pool_->HasGroup("bar")); | |
2818 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("bar")); | |
2819 } | |
2820 | |
2821 TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterFinishingAllRequests) { | |
2822 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
2823 pool_->EnableConnectBackupJobs(); | |
2824 | |
2825 // Create the first socket and set to ERR_IO_PENDING. This starts the backup | |
2826 // timer. | |
2827 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2828 ClientSocketHandle handle; | |
2829 TestCompletionCallback callback; | |
2830 EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar", | |
2831 params_, | |
2832 DEFAULT_PRIORITY, | |
2833 callback.callback(), | |
2834 pool_.get(), | |
2835 BoundNetLog())); | |
2836 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2837 ClientSocketHandle handle2; | |
2838 TestCompletionCallback callback2; | |
2839 EXPECT_EQ(ERR_IO_PENDING, handle2.Init("bar", | |
2840 params_, | |
2841 DEFAULT_PRIORITY, | |
2842 callback2.callback(), | |
2843 pool_.get(), | |
2844 BoundNetLog())); | |
2845 ASSERT_TRUE(pool_->HasGroup("bar")); | |
2846 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("bar")); | |
2847 | |
2848 // Cancel request 1 and then complete request 2. With the requests finished, | |
2849 // the backup timer should be cancelled. | |
2850 handle.Reset(); | |
2851 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2852 // Wait for the backup timer to fire (add some slop to ensure it fires) | |
2853 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( | |
2854 ClientSocketPool::kMaxConnectRetryIntervalMs / 2 * 3)); | |
2855 base::MessageLoop::current()->RunUntilIdle(); | |
2856 } | |
2857 | |
2858 // Test delayed socket binding for the case where we have two connects, | |
2859 // and while one is waiting on a connect, the other frees up. | |
2860 // The socket waiting on a connect should switch immediately to the freed | |
2861 // up socket. | |
2862 TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingWaitingForConnect) { | |
2863 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2864 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2865 | |
2866 ClientSocketHandle handle1; | |
2867 TestCompletionCallback callback; | |
2868 EXPECT_EQ(ERR_IO_PENDING, | |
2869 handle1.Init("a", | |
2870 params_, | |
2871 DEFAULT_PRIORITY, | |
2872 callback.callback(), | |
2873 pool_.get(), | |
2874 BoundNetLog())); | |
2875 EXPECT_EQ(OK, callback.WaitForResult()); | |
2876 | |
2877 // No idle sockets, no pending jobs. | |
2878 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2879 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
2880 | |
2881 // Create a second socket to the same host, but this one will wait. | |
2882 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2883 ClientSocketHandle handle2; | |
2884 EXPECT_EQ(ERR_IO_PENDING, | |
2885 handle2.Init("a", | |
2886 params_, | |
2887 DEFAULT_PRIORITY, | |
2888 callback.callback(), | |
2889 pool_.get(), | |
2890 BoundNetLog())); | |
2891 // No idle sockets, and one connecting job. | |
2892 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2893 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
2894 | |
2895 // Return the first handle to the pool. This will initiate the delayed | |
2896 // binding. | |
2897 handle1.Reset(); | |
2898 | |
2899 base::MessageLoop::current()->RunUntilIdle(); | |
2900 | |
2901 // Still no idle sockets, still one pending connect job. | |
2902 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2903 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
2904 | |
2905 // The second socket connected, even though it was a Waiting Job. | |
2906 EXPECT_EQ(OK, callback.WaitForResult()); | |
2907 | |
2908 // And we can see there is still one job waiting. | |
2909 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
2910 | |
2911 // Finally, signal the waiting Connect. | |
2912 client_socket_factory_.SignalJobs(); | |
2913 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
2914 | |
2915 base::MessageLoop::current()->RunUntilIdle(); | |
2916 } | |
2917 | |
2918 // Test delayed socket binding when a group is at capacity and one | |
2919 // of the group's sockets frees up. | |
2920 TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtGroupCapacity) { | |
2921 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2922 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2923 | |
2924 ClientSocketHandle handle1; | |
2925 TestCompletionCallback callback; | |
2926 EXPECT_EQ(ERR_IO_PENDING, | |
2927 handle1.Init("a", | |
2928 params_, | |
2929 DEFAULT_PRIORITY, | |
2930 callback.callback(), | |
2931 pool_.get(), | |
2932 BoundNetLog())); | |
2933 EXPECT_EQ(OK, callback.WaitForResult()); | |
2934 | |
2935 // No idle sockets, no pending jobs. | |
2936 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2937 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
2938 | |
2939 // Create a second socket to the same host, but this one will wait. | |
2940 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
2941 ClientSocketHandle handle2; | |
2942 EXPECT_EQ(ERR_IO_PENDING, | |
2943 handle2.Init("a", | |
2944 params_, | |
2945 DEFAULT_PRIORITY, | |
2946 callback.callback(), | |
2947 pool_.get(), | |
2948 BoundNetLog())); | |
2949 // No idle sockets, and one connecting job. | |
2950 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2951 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
2952 | |
2953 // Return the first handle to the pool. This will initiate the delayed | |
2954 // binding. | |
2955 handle1.Reset(); | |
2956 | |
2957 base::MessageLoop::current()->RunUntilIdle(); | |
2958 | |
2959 // Still no idle sockets, still one pending connect job. | |
2960 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2961 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
2962 | |
2963 // The second socket connected, even though it was a Waiting Job. | |
2964 EXPECT_EQ(OK, callback.WaitForResult()); | |
2965 | |
2966 // And we can see there is still one job waiting. | |
2967 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
2968 | |
2969 // Finally, signal the waiting Connect. | |
2970 client_socket_factory_.SignalJobs(); | |
2971 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
2972 | |
2973 base::MessageLoop::current()->RunUntilIdle(); | |
2974 } | |
2975 | |
2976 // Test out the case where we have one socket connected, one | |
2977 // connecting, when the first socket finishes and goes idle. | |
2978 // Although the second connection is pending, the second request | |
2979 // should complete, by taking the first socket's idle socket. | |
2980 TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtStall) { | |
2981 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
2982 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
2983 | |
2984 ClientSocketHandle handle1; | |
2985 TestCompletionCallback callback; | |
2986 EXPECT_EQ(ERR_IO_PENDING, | |
2987 handle1.Init("a", | |
2988 params_, | |
2989 DEFAULT_PRIORITY, | |
2990 callback.callback(), | |
2991 pool_.get(), | |
2992 BoundNetLog())); | |
2993 EXPECT_EQ(OK, callback.WaitForResult()); | |
2994 | |
2995 // No idle sockets, no pending jobs. | |
2996 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
2997 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
2998 | |
2999 // Create a second socket to the same host, but this one will wait. | |
3000 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
3001 ClientSocketHandle handle2; | |
3002 EXPECT_EQ(ERR_IO_PENDING, | |
3003 handle2.Init("a", | |
3004 params_, | |
3005 DEFAULT_PRIORITY, | |
3006 callback.callback(), | |
3007 pool_.get(), | |
3008 BoundNetLog())); | |
3009 // No idle sockets, and one connecting job. | |
3010 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
3011 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3012 | |
3013 // Return the first handle to the pool. This will initiate the delayed | |
3014 // binding. | |
3015 handle1.Reset(); | |
3016 | |
3017 base::MessageLoop::current()->RunUntilIdle(); | |
3018 | |
3019 // Still no idle sockets, still one pending connect job. | |
3020 EXPECT_EQ(0, pool_->IdleSocketCount()); | |
3021 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3022 | |
3023 // The second socket connected, even though it was a Waiting Job. | |
3024 EXPECT_EQ(OK, callback.WaitForResult()); | |
3025 | |
3026 // And we can see there is still one job waiting. | |
3027 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3028 | |
3029 // Finally, signal the waiting Connect. | |
3030 client_socket_factory_.SignalJobs(); | |
3031 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3032 | |
3033 base::MessageLoop::current()->RunUntilIdle(); | |
3034 } | |
3035 | |
3036 // Cover the case where on an available socket slot, we have one pending | |
3037 // request that completes synchronously, thereby making the Group empty. | |
3038 TEST_F(ClientSocketPoolBaseTest, SynchronouslyProcessOnePendingRequest) { | |
3039 const int kUnlimitedSockets = 100; | |
3040 const int kOneSocketPerGroup = 1; | |
3041 CreatePool(kUnlimitedSockets, kOneSocketPerGroup); | |
3042 | |
3043 // Make the first request asynchronous fail. | |
3044 // This will free up a socket slot later. | |
3045 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | |
3046 | |
3047 ClientSocketHandle handle1; | |
3048 TestCompletionCallback callback1; | |
3049 EXPECT_EQ(ERR_IO_PENDING, | |
3050 handle1.Init("a", | |
3051 params_, | |
3052 DEFAULT_PRIORITY, | |
3053 callback1.callback(), | |
3054 pool_.get(), | |
3055 BoundNetLog())); | |
3056 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3057 | |
3058 // Make the second request synchronously fail. This should make the Group | |
3059 // empty. | |
3060 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | |
3061 ClientSocketHandle handle2; | |
3062 TestCompletionCallback callback2; | |
3063 // It'll be ERR_IO_PENDING now, but the TestConnectJob will synchronously fail | |
3064 // when created. | |
3065 EXPECT_EQ(ERR_IO_PENDING, | |
3066 handle2.Init("a", | |
3067 params_, | |
3068 DEFAULT_PRIORITY, | |
3069 callback2.callback(), | |
3070 pool_.get(), | |
3071 BoundNetLog())); | |
3072 | |
3073 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3074 | |
3075 EXPECT_EQ(ERR_CONNECTION_FAILED, callback1.WaitForResult()); | |
3076 EXPECT_EQ(ERR_CONNECTION_FAILED, callback2.WaitForResult()); | |
3077 EXPECT_FALSE(pool_->HasGroup("a")); | |
3078 } | |
3079 | |
3080 TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) { | |
3081 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
3082 | |
3083 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3084 | |
3085 ClientSocketHandle handle1; | |
3086 TestCompletionCallback callback1; | |
3087 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3088 params_, | |
3089 DEFAULT_PRIORITY, | |
3090 callback1.callback(), | |
3091 pool_.get(), | |
3092 BoundNetLog())); | |
3093 | |
3094 ClientSocketHandle handle2; | |
3095 TestCompletionCallback callback2; | |
3096 EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a", | |
3097 params_, | |
3098 DEFAULT_PRIORITY, | |
3099 callback2.callback(), | |
3100 pool_.get(), | |
3101 BoundNetLog())); | |
3102 ClientSocketHandle handle3; | |
3103 TestCompletionCallback callback3; | |
3104 EXPECT_EQ(ERR_IO_PENDING, handle3.Init("a", | |
3105 params_, | |
3106 DEFAULT_PRIORITY, | |
3107 callback3.callback(), | |
3108 pool_.get(), | |
3109 BoundNetLog())); | |
3110 | |
3111 EXPECT_EQ(OK, callback1.WaitForResult()); | |
3112 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3113 EXPECT_EQ(OK, callback3.WaitForResult()); | |
3114 | |
3115 // Use the socket. | |
3116 EXPECT_EQ(1, handle1.socket()->Write(NULL, 1, CompletionCallback())); | |
3117 EXPECT_EQ(1, handle3.socket()->Write(NULL, 1, CompletionCallback())); | |
3118 | |
3119 handle1.Reset(); | |
3120 handle2.Reset(); | |
3121 handle3.Reset(); | |
3122 | |
3123 EXPECT_EQ(OK, handle1.Init("a", | |
3124 params_, | |
3125 DEFAULT_PRIORITY, | |
3126 callback1.callback(), | |
3127 pool_.get(), | |
3128 BoundNetLog())); | |
3129 EXPECT_EQ(OK, handle2.Init("a", | |
3130 params_, | |
3131 DEFAULT_PRIORITY, | |
3132 callback2.callback(), | |
3133 pool_.get(), | |
3134 BoundNetLog())); | |
3135 EXPECT_EQ(OK, handle3.Init("a", | |
3136 params_, | |
3137 DEFAULT_PRIORITY, | |
3138 callback3.callback(), | |
3139 pool_.get(), | |
3140 BoundNetLog())); | |
3141 | |
3142 EXPECT_TRUE(handle1.socket()->WasEverUsed()); | |
3143 EXPECT_TRUE(handle2.socket()->WasEverUsed()); | |
3144 EXPECT_FALSE(handle3.socket()->WasEverUsed()); | |
3145 } | |
3146 | |
3147 TEST_F(ClientSocketPoolBaseTest, RequestSockets) { | |
3148 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3149 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3150 | |
3151 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3152 | |
3153 ASSERT_TRUE(pool_->HasGroup("a")); | |
3154 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3155 EXPECT_EQ(2, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3156 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3157 | |
3158 ClientSocketHandle handle1; | |
3159 TestCompletionCallback callback1; | |
3160 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3161 params_, | |
3162 DEFAULT_PRIORITY, | |
3163 callback1.callback(), | |
3164 pool_.get(), | |
3165 BoundNetLog())); | |
3166 | |
3167 ClientSocketHandle handle2; | |
3168 TestCompletionCallback callback2; | |
3169 EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a", | |
3170 params_, | |
3171 DEFAULT_PRIORITY, | |
3172 callback2.callback(), | |
3173 pool_.get(), | |
3174 BoundNetLog())); | |
3175 | |
3176 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3177 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3178 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3179 | |
3180 EXPECT_EQ(OK, callback1.WaitForResult()); | |
3181 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3182 handle1.Reset(); | |
3183 handle2.Reset(); | |
3184 | |
3185 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3186 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3187 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a")); | |
3188 } | |
3189 | |
3190 TEST_F(ClientSocketPoolBaseTest, RequestSocketsWhenAlreadyHaveAConnectJob) { | |
3191 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3192 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3193 | |
3194 ClientSocketHandle handle1; | |
3195 TestCompletionCallback callback1; | |
3196 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3197 params_, | |
3198 DEFAULT_PRIORITY, | |
3199 callback1.callback(), | |
3200 pool_.get(), | |
3201 BoundNetLog())); | |
3202 | |
3203 ASSERT_TRUE(pool_->HasGroup("a")); | |
3204 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3205 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3206 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3207 | |
3208 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3209 | |
3210 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3211 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3212 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3213 | |
3214 ClientSocketHandle handle2; | |
3215 TestCompletionCallback callback2; | |
3216 EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a", | |
3217 params_, | |
3218 DEFAULT_PRIORITY, | |
3219 callback2.callback(), | |
3220 pool_.get(), | |
3221 BoundNetLog())); | |
3222 | |
3223 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3224 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3225 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3226 | |
3227 EXPECT_EQ(OK, callback1.WaitForResult()); | |
3228 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3229 handle1.Reset(); | |
3230 handle2.Reset(); | |
3231 | |
3232 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3233 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3234 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a")); | |
3235 } | |
3236 | |
3237 TEST_F(ClientSocketPoolBaseTest, | |
3238 RequestSocketsWhenAlreadyHaveMultipleConnectJob) { | |
3239 CreatePool(4, 4); | |
3240 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3241 | |
3242 ClientSocketHandle handle1; | |
3243 TestCompletionCallback callback1; | |
3244 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3245 params_, | |
3246 DEFAULT_PRIORITY, | |
3247 callback1.callback(), | |
3248 pool_.get(), | |
3249 BoundNetLog())); | |
3250 | |
3251 ClientSocketHandle handle2; | |
3252 TestCompletionCallback callback2; | |
3253 EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a", | |
3254 params_, | |
3255 DEFAULT_PRIORITY, | |
3256 callback2.callback(), | |
3257 pool_.get(), | |
3258 BoundNetLog())); | |
3259 | |
3260 ClientSocketHandle handle3; | |
3261 TestCompletionCallback callback3; | |
3262 EXPECT_EQ(ERR_IO_PENDING, handle3.Init("a", | |
3263 params_, | |
3264 DEFAULT_PRIORITY, | |
3265 callback3.callback(), | |
3266 pool_.get(), | |
3267 BoundNetLog())); | |
3268 | |
3269 ASSERT_TRUE(pool_->HasGroup("a")); | |
3270 EXPECT_EQ(3, pool_->NumConnectJobsInGroup("a")); | |
3271 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3272 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3273 | |
3274 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3275 | |
3276 EXPECT_EQ(3, pool_->NumConnectJobsInGroup("a")); | |
3277 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3278 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3279 | |
3280 EXPECT_EQ(OK, callback1.WaitForResult()); | |
3281 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3282 EXPECT_EQ(OK, callback3.WaitForResult()); | |
3283 handle1.Reset(); | |
3284 handle2.Reset(); | |
3285 handle3.Reset(); | |
3286 | |
3287 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3288 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3289 EXPECT_EQ(3, pool_->IdleSocketCountInGroup("a")); | |
3290 } | |
3291 | |
3292 TEST_F(ClientSocketPoolBaseTest, RequestSocketsAtMaxSocketLimit) { | |
3293 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
3294 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3295 | |
3296 ASSERT_FALSE(pool_->HasGroup("a")); | |
3297 | |
3298 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSockets, | |
3299 BoundNetLog()); | |
3300 | |
3301 ASSERT_TRUE(pool_->HasGroup("a")); | |
3302 EXPECT_EQ(kDefaultMaxSockets, pool_->NumConnectJobsInGroup("a")); | |
3303 EXPECT_EQ(kDefaultMaxSockets, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3304 | |
3305 ASSERT_FALSE(pool_->HasGroup("b")); | |
3306 | |
3307 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSockets, | |
3308 BoundNetLog()); | |
3309 | |
3310 ASSERT_FALSE(pool_->HasGroup("b")); | |
3311 } | |
3312 | |
3313 TEST_F(ClientSocketPoolBaseTest, RequestSocketsHitMaxSocketLimit) { | |
3314 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | |
3315 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3316 | |
3317 ASSERT_FALSE(pool_->HasGroup("a")); | |
3318 | |
3319 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSockets - 1, | |
3320 BoundNetLog()); | |
3321 | |
3322 ASSERT_TRUE(pool_->HasGroup("a")); | |
3323 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); | |
3324 EXPECT_EQ(kDefaultMaxSockets - 1, | |
3325 pool_->NumUnassignedConnectJobsInGroup("a")); | |
3326 EXPECT_FALSE(pool_->IsStalled()); | |
3327 | |
3328 ASSERT_FALSE(pool_->HasGroup("b")); | |
3329 | |
3330 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSockets, | |
3331 BoundNetLog()); | |
3332 | |
3333 ASSERT_TRUE(pool_->HasGroup("b")); | |
3334 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); | |
3335 EXPECT_FALSE(pool_->IsStalled()); | |
3336 } | |
3337 | |
3338 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { | |
3339 CreatePool(4, 4); | |
3340 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3341 | |
3342 ClientSocketHandle handle1; | |
3343 TestCompletionCallback callback1; | |
3344 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3345 params_, | |
3346 DEFAULT_PRIORITY, | |
3347 callback1.callback(), | |
3348 pool_.get(), | |
3349 BoundNetLog())); | |
3350 ASSERT_EQ(OK, callback1.WaitForResult()); | |
3351 handle1.Reset(); | |
3352 | |
3353 ASSERT_TRUE(pool_->HasGroup("a")); | |
3354 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3355 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3356 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3357 | |
3358 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3359 | |
3360 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3361 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3362 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3363 } | |
3364 | |
3365 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountActiveSockets) { | |
3366 CreatePool(4, 4); | |
3367 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3368 | |
3369 ClientSocketHandle handle1; | |
3370 TestCompletionCallback callback1; | |
3371 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3372 params_, | |
3373 DEFAULT_PRIORITY, | |
3374 callback1.callback(), | |
3375 pool_.get(), | |
3376 BoundNetLog())); | |
3377 ASSERT_EQ(OK, callback1.WaitForResult()); | |
3378 | |
3379 ASSERT_TRUE(pool_->HasGroup("a")); | |
3380 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3381 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3382 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3383 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | |
3384 | |
3385 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3386 | |
3387 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3388 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3389 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3390 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | |
3391 } | |
3392 | |
3393 TEST_F(ClientSocketPoolBaseTest, RequestSocketsSynchronous) { | |
3394 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3395 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3396 | |
3397 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSocketsPerGroup, | |
3398 BoundNetLog()); | |
3399 | |
3400 ASSERT_TRUE(pool_->HasGroup("a")); | |
3401 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3402 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3403 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->IdleSocketCountInGroup("a")); | |
3404 | |
3405 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSocketsPerGroup, | |
3406 BoundNetLog()); | |
3407 | |
3408 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("b")); | |
3409 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("b")); | |
3410 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->IdleSocketCountInGroup("b")); | |
3411 } | |
3412 | |
3413 TEST_F(ClientSocketPoolBaseTest, RequestSocketsSynchronousError) { | |
3414 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3415 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | |
3416 | |
3417 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSocketsPerGroup, | |
3418 BoundNetLog()); | |
3419 | |
3420 ASSERT_FALSE(pool_->HasGroup("a")); | |
3421 | |
3422 connect_job_factory_->set_job_type( | |
3423 TestConnectJob::kMockAdditionalErrorStateJob); | |
3424 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSocketsPerGroup, | |
3425 BoundNetLog()); | |
3426 | |
3427 ASSERT_FALSE(pool_->HasGroup("a")); | |
3428 } | |
3429 | |
3430 TEST_F(ClientSocketPoolBaseTest, RequestSocketsMultipleTimesDoesNothing) { | |
3431 CreatePool(4, 4); | |
3432 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3433 | |
3434 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3435 | |
3436 ASSERT_TRUE(pool_->HasGroup("a")); | |
3437 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3438 EXPECT_EQ(2, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3439 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3440 | |
3441 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3442 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3443 EXPECT_EQ(2, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3444 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3445 | |
3446 ClientSocketHandle handle1; | |
3447 TestCompletionCallback callback1; | |
3448 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3449 params_, | |
3450 DEFAULT_PRIORITY, | |
3451 callback1.callback(), | |
3452 pool_.get(), | |
3453 BoundNetLog())); | |
3454 ASSERT_EQ(OK, callback1.WaitForResult()); | |
3455 | |
3456 ClientSocketHandle handle2; | |
3457 TestCompletionCallback callback2; | |
3458 int rv = handle2.Init("a", | |
3459 params_, | |
3460 DEFAULT_PRIORITY, | |
3461 callback2.callback(), | |
3462 pool_.get(), | |
3463 BoundNetLog()); | |
3464 if (rv != OK) { | |
3465 EXPECT_EQ(ERR_IO_PENDING, rv); | |
3466 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3467 } | |
3468 | |
3469 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3470 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3471 EXPECT_EQ(2, pool_->NumActiveSocketsInGroup("a")); | |
3472 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3473 | |
3474 handle1.Reset(); | |
3475 handle2.Reset(); | |
3476 | |
3477 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3478 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3479 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a")); | |
3480 | |
3481 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3482 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3483 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3484 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a")); | |
3485 } | |
3486 | |
3487 TEST_F(ClientSocketPoolBaseTest, RequestSocketsDifferentNumSockets) { | |
3488 CreatePool(4, 4); | |
3489 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3490 | |
3491 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3492 | |
3493 ASSERT_TRUE(pool_->HasGroup("a")); | |
3494 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3495 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3496 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3497 | |
3498 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3499 EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a")); | |
3500 EXPECT_EQ(2, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3501 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3502 | |
3503 pool_->RequestSockets("a", ¶ms_, 3, BoundNetLog()); | |
3504 EXPECT_EQ(3, pool_->NumConnectJobsInGroup("a")); | |
3505 EXPECT_EQ(3, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3506 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3507 | |
3508 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3509 EXPECT_EQ(3, pool_->NumConnectJobsInGroup("a")); | |
3510 EXPECT_EQ(3, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3511 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3512 } | |
3513 | |
3514 TEST_F(ClientSocketPoolBaseTest, PreconnectJobsTakenByNormalRequests) { | |
3515 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3516 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3517 | |
3518 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3519 | |
3520 ASSERT_TRUE(pool_->HasGroup("a")); | |
3521 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3522 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3523 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3524 | |
3525 ClientSocketHandle handle1; | |
3526 TestCompletionCallback callback1; | |
3527 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3528 params_, | |
3529 DEFAULT_PRIORITY, | |
3530 callback1.callback(), | |
3531 pool_.get(), | |
3532 BoundNetLog())); | |
3533 | |
3534 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3535 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3536 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3537 | |
3538 ASSERT_EQ(OK, callback1.WaitForResult()); | |
3539 | |
3540 // Make sure if a preconnected socket is not fully connected when a request | |
3541 // starts, it has a connect start time. | |
3542 TestLoadTimingInfoConnectedNotReused(handle1); | |
3543 handle1.Reset(); | |
3544 | |
3545 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3546 } | |
3547 | |
3548 // Checks that fully connected preconnect jobs have no connect times, and are | |
3549 // marked as reused. | |
3550 TEST_F(ClientSocketPoolBaseTest, ConnectedPreconnectJobsHaveNoConnectTimes) { | |
3551 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3552 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3553 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3554 | |
3555 ASSERT_TRUE(pool_->HasGroup("a")); | |
3556 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3557 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3558 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3559 | |
3560 ClientSocketHandle handle; | |
3561 TestCompletionCallback callback; | |
3562 EXPECT_EQ(OK, handle.Init("a", | |
3563 params_, | |
3564 DEFAULT_PRIORITY, | |
3565 callback.callback(), | |
3566 pool_.get(), | |
3567 BoundNetLog())); | |
3568 | |
3569 // Make sure the idle socket was used. | |
3570 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3571 | |
3572 TestLoadTimingInfoConnectedReused(handle); | |
3573 handle.Reset(); | |
3574 TestLoadTimingInfoNotConnected(handle); | |
3575 } | |
3576 | |
3577 // http://crbug.com/64940 regression test. | |
3578 TEST_F(ClientSocketPoolBaseTest, PreconnectClosesIdleSocketRemovesGroup) { | |
3579 const int kMaxTotalSockets = 3; | |
3580 const int kMaxSocketsPerGroup = 2; | |
3581 CreatePool(kMaxTotalSockets, kMaxSocketsPerGroup); | |
3582 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3583 | |
3584 // Note that group name ordering matters here. "a" comes before "b", so | |
3585 // CloseOneIdleSocket() will try to close "a"'s idle socket. | |
3586 | |
3587 // Set up one idle socket in "a". | |
3588 ClientSocketHandle handle1; | |
3589 TestCompletionCallback callback1; | |
3590 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | |
3591 params_, | |
3592 DEFAULT_PRIORITY, | |
3593 callback1.callback(), | |
3594 pool_.get(), | |
3595 BoundNetLog())); | |
3596 | |
3597 ASSERT_EQ(OK, callback1.WaitForResult()); | |
3598 handle1.Reset(); | |
3599 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3600 | |
3601 // Set up two active sockets in "b". | |
3602 ClientSocketHandle handle2; | |
3603 TestCompletionCallback callback2; | |
3604 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("b", | |
3605 params_, | |
3606 DEFAULT_PRIORITY, | |
3607 callback1.callback(), | |
3608 pool_.get(), | |
3609 BoundNetLog())); | |
3610 EXPECT_EQ(ERR_IO_PENDING, handle2.Init("b", | |
3611 params_, | |
3612 DEFAULT_PRIORITY, | |
3613 callback2.callback(), | |
3614 pool_.get(), | |
3615 BoundNetLog())); | |
3616 | |
3617 ASSERT_EQ(OK, callback1.WaitForResult()); | |
3618 ASSERT_EQ(OK, callback2.WaitForResult()); | |
3619 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("b")); | |
3620 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("b")); | |
3621 EXPECT_EQ(2, pool_->NumActiveSocketsInGroup("b")); | |
3622 | |
3623 // Now we have 1 idle socket in "a" and 2 active sockets in "b". This means | |
3624 // we've maxed out on sockets, since we set |kMaxTotalSockets| to 3. | |
3625 // Requesting 2 preconnected sockets for "a" should fail to allocate any more | |
3626 // sockets for "a", and "b" should still have 2 active sockets. | |
3627 | |
3628 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3629 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3630 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3631 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3632 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); | |
3633 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("b")); | |
3634 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("b")); | |
3635 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("b")); | |
3636 EXPECT_EQ(2, pool_->NumActiveSocketsInGroup("b")); | |
3637 | |
3638 // Now release the 2 active sockets for "b". This will give us 1 idle socket | |
3639 // in "a" and 2 idle sockets in "b". Requesting 2 preconnected sockets for | |
3640 // "a" should result in closing 1 for "b". | |
3641 handle1.Reset(); | |
3642 handle2.Reset(); | |
3643 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("b")); | |
3644 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("b")); | |
3645 | |
3646 pool_->RequestSockets("a", ¶ms_, 2, BoundNetLog()); | |
3647 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3648 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3649 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3650 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); | |
3651 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("b")); | |
3652 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("b")); | |
3653 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("b")); | |
3654 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("b")); | |
3655 } | |
3656 | |
3657 TEST_F(ClientSocketPoolBaseTest, PreconnectWithoutBackupJob) { | |
3658 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3659 pool_->EnableConnectBackupJobs(); | |
3660 | |
3661 // Make the ConnectJob hang until it times out, shorten the timeout. | |
3662 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
3663 connect_job_factory_->set_timeout_duration( | |
3664 base::TimeDelta::FromMilliseconds(500)); | |
3665 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3666 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3667 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3668 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3669 | |
3670 // Verify the backup timer doesn't create a backup job, by making | |
3671 // the backup job a pending job instead of a waiting job, so it | |
3672 // *would* complete if it were created. | |
3673 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3674 base::MessageLoop::current()->PostDelayedTask( | |
3675 FROM_HERE, | |
3676 base::MessageLoop::QuitClosure(), | |
3677 base::TimeDelta::FromSeconds(1)); | |
3678 base::MessageLoop::current()->Run(); | |
3679 EXPECT_FALSE(pool_->HasGroup("a")); | |
3680 } | |
3681 | |
3682 TEST_F(ClientSocketPoolBaseTest, PreconnectWithBackupJob) { | |
3683 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3684 pool_->EnableConnectBackupJobs(); | |
3685 | |
3686 // Make the ConnectJob hang forever. | |
3687 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); | |
3688 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3689 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3690 EXPECT_EQ(1, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3691 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3692 base::MessageLoop::current()->RunUntilIdle(); | |
3693 | |
3694 // Make the backup job be a pending job, so it completes normally. | |
3695 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
3696 ClientSocketHandle handle; | |
3697 TestCompletionCallback callback; | |
3698 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
3699 params_, | |
3700 DEFAULT_PRIORITY, | |
3701 callback.callback(), | |
3702 pool_.get(), | |
3703 BoundNetLog())); | |
3704 // Timer has started, but the backup connect job shouldn't be created yet. | |
3705 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3706 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3707 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3708 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); | |
3709 ASSERT_EQ(OK, callback.WaitForResult()); | |
3710 | |
3711 // The hung connect job should still be there, but everything else should be | |
3712 // complete. | |
3713 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
3714 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3715 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3716 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | |
3717 } | |
3718 | |
3719 // Tests that a preconnect that starts out with unread data can still be used. | |
3720 // http://crbug.com/334467 | |
3721 TEST_F(ClientSocketPoolBaseTest, PreconnectWithUnreadData) { | |
3722 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3723 connect_job_factory_->set_job_type(TestConnectJob::kMockUnreadDataJob); | |
3724 | |
3725 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
3726 | |
3727 ASSERT_TRUE(pool_->HasGroup("a")); | |
3728 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3729 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3730 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3731 | |
3732 // Fail future jobs to be sure that handle receives the preconnected socket | |
3733 // rather than closing it and making a new one. | |
3734 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | |
3735 ClientSocketHandle handle; | |
3736 TestCompletionCallback callback; | |
3737 EXPECT_EQ(OK, handle.Init("a", | |
3738 params_, | |
3739 DEFAULT_PRIORITY, | |
3740 callback.callback(), | |
3741 pool_.get(), | |
3742 BoundNetLog())); | |
3743 | |
3744 ASSERT_TRUE(pool_->HasGroup("a")); | |
3745 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
3746 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
3747 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
3748 | |
3749 // Drain the pending read. | |
3750 EXPECT_EQ(1, handle.socket()->Read(NULL, 1, CompletionCallback())); | |
3751 | |
3752 TestLoadTimingInfoConnectedReused(handle); | |
3753 handle.Reset(); | |
3754 | |
3755 // The socket should be usable now that it's idle again. | |
3756 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
3757 } | |
3758 | |
3759 class MockLayeredPool : public HigherLayeredPool { | |
3760 public: | |
3761 MockLayeredPool(TestClientSocketPool* pool, | |
3762 const std::string& group_name) | |
3763 : pool_(pool), | |
3764 group_name_(group_name), | |
3765 can_release_connection_(true) { | |
3766 pool_->AddHigherLayeredPool(this); | |
3767 } | |
3768 | |
3769 ~MockLayeredPool() { | |
3770 pool_->RemoveHigherLayeredPool(this); | |
3771 } | |
3772 | |
3773 int RequestSocket(TestClientSocketPool* pool) { | |
3774 scoped_refptr<TestSocketParams> params( | |
3775 new TestSocketParams(false /* ignore_limits */)); | |
3776 return handle_.Init(group_name_, params, DEFAULT_PRIORITY, | |
3777 callback_.callback(), pool, BoundNetLog()); | |
3778 } | |
3779 | |
3780 int RequestSocketWithoutLimits(TestClientSocketPool* pool) { | |
3781 scoped_refptr<TestSocketParams> params( | |
3782 new TestSocketParams(true /* ignore_limits */)); | |
3783 return handle_.Init(group_name_, params, MAXIMUM_PRIORITY, | |
3784 callback_.callback(), pool, BoundNetLog()); | |
3785 } | |
3786 | |
3787 bool ReleaseOneConnection() { | |
3788 if (!handle_.is_initialized() || !can_release_connection_) { | |
3789 return false; | |
3790 } | |
3791 handle_.socket()->Disconnect(); | |
3792 handle_.Reset(); | |
3793 return true; | |
3794 } | |
3795 | |
3796 void set_can_release_connection(bool can_release_connection) { | |
3797 can_release_connection_ = can_release_connection; | |
3798 } | |
3799 | |
3800 MOCK_METHOD0(CloseOneIdleConnection, bool()); | |
3801 | |
3802 private: | |
3803 TestClientSocketPool* const pool_; | |
3804 ClientSocketHandle handle_; | |
3805 TestCompletionCallback callback_; | |
3806 const std::string group_name_; | |
3807 bool can_release_connection_; | |
3808 }; | |
3809 | |
3810 TEST_F(ClientSocketPoolBaseTest, FailToCloseIdleSocketsNotHeldByLayeredPool) { | |
3811 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3812 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3813 | |
3814 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); | |
3815 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3816 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3817 .WillOnce(Return(false)); | |
3818 EXPECT_FALSE(pool_->CloseOneIdleConnectionInHigherLayeredPool()); | |
3819 } | |
3820 | |
3821 TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) { | |
3822 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3823 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3824 | |
3825 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); | |
3826 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3827 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3828 .WillOnce(Invoke(&mock_layered_pool, | |
3829 &MockLayeredPool::ReleaseOneConnection)); | |
3830 EXPECT_TRUE(pool_->CloseOneIdleConnectionInHigherLayeredPool()); | |
3831 } | |
3832 | |
3833 // Tests the basic case of closing an idle socket in a higher layered pool when | |
3834 // a new request is issued and the lower layer pool is stalled. | |
3835 TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) { | |
3836 CreatePool(1, 1); | |
3837 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3838 | |
3839 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); | |
3840 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3841 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3842 .WillOnce(Invoke(&mock_layered_pool, | |
3843 &MockLayeredPool::ReleaseOneConnection)); | |
3844 ClientSocketHandle handle; | |
3845 TestCompletionCallback callback; | |
3846 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
3847 params_, | |
3848 DEFAULT_PRIORITY, | |
3849 callback.callback(), | |
3850 pool_.get(), | |
3851 BoundNetLog())); | |
3852 EXPECT_EQ(OK, callback.WaitForResult()); | |
3853 } | |
3854 | |
3855 // Same as above, but the idle socket is in the same group as the stalled | |
3856 // socket, and closes the only other request in its group when closing requests | |
3857 // in higher layered pools. This generally shouldn't happen, but it may be | |
3858 // possible if a higher level pool issues a request and the request is | |
3859 // subsequently cancelled. Even if it's not possible, best not to crash. | |
3860 TEST_F(ClientSocketPoolBaseTest, | |
3861 CloseIdleSocketsHeldByLayeredPoolWhenNeededSameGroup) { | |
3862 CreatePool(2, 2); | |
3863 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3864 | |
3865 // Need a socket in another group for the pool to be stalled (If a group | |
3866 // has the maximum number of connections already, it's not stalled). | |
3867 ClientSocketHandle handle1; | |
3868 TestCompletionCallback callback1; | |
3869 EXPECT_EQ(OK, handle1.Init("group1", | |
3870 params_, | |
3871 DEFAULT_PRIORITY, | |
3872 callback1.callback(), | |
3873 pool_.get(), | |
3874 BoundNetLog())); | |
3875 | |
3876 MockLayeredPool mock_layered_pool(pool_.get(), "group2"); | |
3877 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3878 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3879 .WillOnce(Invoke(&mock_layered_pool, | |
3880 &MockLayeredPool::ReleaseOneConnection)); | |
3881 ClientSocketHandle handle; | |
3882 TestCompletionCallback callback2; | |
3883 EXPECT_EQ(ERR_IO_PENDING, handle.Init("group2", | |
3884 params_, | |
3885 DEFAULT_PRIORITY, | |
3886 callback2.callback(), | |
3887 pool_.get(), | |
3888 BoundNetLog())); | |
3889 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3890 } | |
3891 | |
3892 // Tests the case when an idle socket can be closed when a new request is | |
3893 // issued, and the new request belongs to a group that was previously stalled. | |
3894 TEST_F(ClientSocketPoolBaseTest, | |
3895 CloseIdleSocketsHeldByLayeredPoolInSameGroupWhenNeeded) { | |
3896 CreatePool(2, 2); | |
3897 std::list<TestConnectJob::JobType> job_types; | |
3898 job_types.push_back(TestConnectJob::kMockJob); | |
3899 job_types.push_back(TestConnectJob::kMockJob); | |
3900 job_types.push_back(TestConnectJob::kMockJob); | |
3901 job_types.push_back(TestConnectJob::kMockJob); | |
3902 connect_job_factory_->set_job_types(&job_types); | |
3903 | |
3904 ClientSocketHandle handle1; | |
3905 TestCompletionCallback callback1; | |
3906 EXPECT_EQ(OK, handle1.Init("group1", | |
3907 params_, | |
3908 DEFAULT_PRIORITY, | |
3909 callback1.callback(), | |
3910 pool_.get(), | |
3911 BoundNetLog())); | |
3912 | |
3913 MockLayeredPool mock_layered_pool(pool_.get(), "group2"); | |
3914 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3915 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3916 .WillRepeatedly(Invoke(&mock_layered_pool, | |
3917 &MockLayeredPool::ReleaseOneConnection)); | |
3918 mock_layered_pool.set_can_release_connection(false); | |
3919 | |
3920 // The third request is made when the socket pool is in a stalled state. | |
3921 ClientSocketHandle handle3; | |
3922 TestCompletionCallback callback3; | |
3923 EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group3", | |
3924 params_, | |
3925 DEFAULT_PRIORITY, | |
3926 callback3.callback(), | |
3927 pool_.get(), | |
3928 BoundNetLog())); | |
3929 | |
3930 base::RunLoop().RunUntilIdle(); | |
3931 EXPECT_FALSE(callback3.have_result()); | |
3932 | |
3933 // The fourth request is made when the pool is no longer stalled. The third | |
3934 // request should be serviced first, since it was issued first and has the | |
3935 // same priority. | |
3936 mock_layered_pool.set_can_release_connection(true); | |
3937 ClientSocketHandle handle4; | |
3938 TestCompletionCallback callback4; | |
3939 EXPECT_EQ(ERR_IO_PENDING, handle4.Init("group3", | |
3940 params_, | |
3941 DEFAULT_PRIORITY, | |
3942 callback4.callback(), | |
3943 pool_.get(), | |
3944 BoundNetLog())); | |
3945 EXPECT_EQ(OK, callback3.WaitForResult()); | |
3946 EXPECT_FALSE(callback4.have_result()); | |
3947 | |
3948 // Closing a handle should free up another socket slot. | |
3949 handle1.Reset(); | |
3950 EXPECT_EQ(OK, callback4.WaitForResult()); | |
3951 } | |
3952 | |
3953 // Tests the case when an idle socket can be closed when a new request is | |
3954 // issued, and the new request belongs to a group that was previously stalled. | |
3955 // | |
3956 // The two differences from the above test are that the stalled requests are not | |
3957 // in the same group as the layered pool's request, and the the fourth request | |
3958 // has a higher priority than the third one, so gets a socket first. | |
3959 TEST_F(ClientSocketPoolBaseTest, | |
3960 CloseIdleSocketsHeldByLayeredPoolInSameGroupWhenNeeded2) { | |
3961 CreatePool(2, 2); | |
3962 std::list<TestConnectJob::JobType> job_types; | |
3963 job_types.push_back(TestConnectJob::kMockJob); | |
3964 job_types.push_back(TestConnectJob::kMockJob); | |
3965 job_types.push_back(TestConnectJob::kMockJob); | |
3966 job_types.push_back(TestConnectJob::kMockJob); | |
3967 connect_job_factory_->set_job_types(&job_types); | |
3968 | |
3969 ClientSocketHandle handle1; | |
3970 TestCompletionCallback callback1; | |
3971 EXPECT_EQ(OK, handle1.Init("group1", | |
3972 params_, | |
3973 DEFAULT_PRIORITY, | |
3974 callback1.callback(), | |
3975 pool_.get(), | |
3976 BoundNetLog())); | |
3977 | |
3978 MockLayeredPool mock_layered_pool(pool_.get(), "group2"); | |
3979 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3980 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3981 .WillRepeatedly(Invoke(&mock_layered_pool, | |
3982 &MockLayeredPool::ReleaseOneConnection)); | |
3983 mock_layered_pool.set_can_release_connection(false); | |
3984 | |
3985 // The third request is made when the socket pool is in a stalled state. | |
3986 ClientSocketHandle handle3; | |
3987 TestCompletionCallback callback3; | |
3988 EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group3", | |
3989 params_, | |
3990 MEDIUM, | |
3991 callback3.callback(), | |
3992 pool_.get(), | |
3993 BoundNetLog())); | |
3994 | |
3995 base::RunLoop().RunUntilIdle(); | |
3996 EXPECT_FALSE(callback3.have_result()); | |
3997 | |
3998 // The fourth request is made when the pool is no longer stalled. This | |
3999 // request has a higher priority than the third request, so is serviced first. | |
4000 mock_layered_pool.set_can_release_connection(true); | |
4001 ClientSocketHandle handle4; | |
4002 TestCompletionCallback callback4; | |
4003 EXPECT_EQ(ERR_IO_PENDING, handle4.Init("group3", | |
4004 params_, | |
4005 HIGHEST, | |
4006 callback4.callback(), | |
4007 pool_.get(), | |
4008 BoundNetLog())); | |
4009 EXPECT_EQ(OK, callback4.WaitForResult()); | |
4010 EXPECT_FALSE(callback3.have_result()); | |
4011 | |
4012 // Closing a handle should free up another socket slot. | |
4013 handle1.Reset(); | |
4014 EXPECT_EQ(OK, callback3.WaitForResult()); | |
4015 } | |
4016 | |
4017 TEST_F(ClientSocketPoolBaseTest, | |
4018 CloseMultipleIdleSocketsHeldByLayeredPoolWhenNeeded) { | |
4019 CreatePool(1, 1); | |
4020 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
4021 | |
4022 MockLayeredPool mock_layered_pool1(pool_.get(), "foo"); | |
4023 EXPECT_EQ(OK, mock_layered_pool1.RequestSocket(pool_.get())); | |
4024 EXPECT_CALL(mock_layered_pool1, CloseOneIdleConnection()) | |
4025 .WillRepeatedly(Invoke(&mock_layered_pool1, | |
4026 &MockLayeredPool::ReleaseOneConnection)); | |
4027 MockLayeredPool mock_layered_pool2(pool_.get(), "bar"); | |
4028 EXPECT_EQ(OK, mock_layered_pool2.RequestSocketWithoutLimits(pool_.get())); | |
4029 EXPECT_CALL(mock_layered_pool2, CloseOneIdleConnection()) | |
4030 .WillRepeatedly(Invoke(&mock_layered_pool2, | |
4031 &MockLayeredPool::ReleaseOneConnection)); | |
4032 ClientSocketHandle handle; | |
4033 TestCompletionCallback callback; | |
4034 EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", | |
4035 params_, | |
4036 DEFAULT_PRIORITY, | |
4037 callback.callback(), | |
4038 pool_.get(), | |
4039 BoundNetLog())); | |
4040 EXPECT_EQ(OK, callback.WaitForResult()); | |
4041 } | |
4042 | |
4043 // Test that when a socket pool and group are at their limits, a request | |
4044 // with |ignore_limits| triggers creation of a new socket, and gets the socket | |
4045 // instead of a request with the same priority that was issued earlier, but | |
4046 // that does not have |ignore_limits| set. | |
4047 TEST_F(ClientSocketPoolBaseTest, IgnoreLimits) { | |
4048 scoped_refptr<TestSocketParams> params_ignore_limits( | |
4049 new TestSocketParams(true /* ignore_limits */)); | |
4050 CreatePool(1, 1); | |
4051 | |
4052 // Issue a request to reach the socket pool limit. | |
4053 EXPECT_EQ(OK, StartRequestWithParams("a", MAXIMUM_PRIORITY, params_)); | |
4054 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
4055 | |
4056 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
4057 | |
4058 EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY, | |
4059 params_)); | |
4060 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
4061 | |
4062 EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY, | |
4063 params_ignore_limits)); | |
4064 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
4065 | |
4066 EXPECT_EQ(OK, request(2)->WaitForResult()); | |
4067 EXPECT_FALSE(request(1)->have_result()); | |
4068 } | |
4069 | |
4070 // Test that when a socket pool and group are at their limits, a ConnectJob | |
4071 // issued for a request with |ignore_limits| set is not cancelled when a request | |
4072 // without |ignore_limits| issued to the same group is cancelled. | |
4073 TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsCancelOtherJob) { | |
4074 scoped_refptr<TestSocketParams> params_ignore_limits( | |
4075 new TestSocketParams(true /* ignore_limits */)); | |
4076 CreatePool(1, 1); | |
4077 | |
4078 // Issue a request to reach the socket pool limit. | |
4079 EXPECT_EQ(OK, StartRequestWithParams("a", MAXIMUM_PRIORITY, params_)); | |
4080 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
4081 | |
4082 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | |
4083 | |
4084 EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY, | |
4085 params_)); | |
4086 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
4087 | |
4088 EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY, | |
4089 params_ignore_limits)); | |
4090 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
4091 | |
4092 // Cancel the pending request without ignore_limits set. The ConnectJob | |
4093 // should not be cancelled. | |
4094 request(1)->handle()->Reset(); | |
4095 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); | |
4096 | |
4097 EXPECT_EQ(OK, request(2)->WaitForResult()); | |
4098 EXPECT_FALSE(request(1)->have_result()); | |
4099 } | |
4100 | |
4101 } // namespace | |
4102 | |
4103 } // namespace net | |
OLD | NEW |