| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/socket/client_socket_pool_base.h" | 5 #include "net/socket/client_socket_pool_base.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/scoped_vector.h" |
| 9 #include "net/base/host_resolver_unittest.h" | 10 #include "net/base/host_resolver_unittest.h" |
| 10 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
| 11 #include "net/base/test_completion_callback.h" | 12 #include "net/base/test_completion_callback.h" |
| 12 #include "net/socket/client_socket.h" | 13 #include "net/socket/client_socket.h" |
| 13 #include "net/socket/client_socket_factory.h" | 14 #include "net/socket/client_socket_factory.h" |
| 14 #include "net/socket/client_socket_handle.h" | 15 #include "net/socket/client_socket_handle.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 17 |
| 17 namespace net { | 18 namespace net { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 const int kMaxSocketsPerGroup = 2; | 22 const int kDefaultMaxSocketsPerGroup = 2; |
| 22 | |
| 23 // Note that the first and the last are the same, the first should be handled | |
| 24 // before the last, since it was inserted first. | |
| 25 const int kPriorities[] = { 1, 3, 4, 2, 1 }; | |
| 26 | |
| 27 // This is the number of extra requests beyond the first few that use up all | |
| 28 // available sockets in the socket group. | |
| 29 const int kNumPendingRequests = arraysize(kPriorities); | |
| 30 | |
| 31 const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests; | |
| 32 | 23 |
| 33 const int kDefaultPriority = 5; | 24 const int kDefaultPriority = 5; |
| 34 | 25 |
| 35 class MockClientSocket : public ClientSocket { | 26 class MockClientSocket : public ClientSocket { |
| 36 public: | 27 public: |
| 37 MockClientSocket() : connected_(false) {} | 28 MockClientSocket() : connected_(false) {} |
| 38 | 29 |
| 39 // Socket methods: | 30 // Socket methods: |
| 40 virtual int Read( | 31 virtual int Read( |
| 41 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { | 32 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 int WaitForResult() { | 97 int WaitForResult() { |
| 107 return callback_.WaitForResult(); | 98 return callback_.WaitForResult(); |
| 108 } | 99 } |
| 109 | 100 |
| 110 virtual void RunWithParams(const Tuple1<int>& params) { | 101 virtual void RunWithParams(const Tuple1<int>& params) { |
| 111 callback_.RunWithParams(params); | 102 callback_.RunWithParams(params); |
| 112 completion_count++; | 103 completion_count++; |
| 113 request_order_->push_back(this); | 104 request_order_->push_back(this); |
| 114 } | 105 } |
| 115 | 106 |
| 116 static int completion_count; | 107 static size_t completion_count; |
| 117 | 108 |
| 118 private: | 109 private: |
| 119 std::vector<TestSocketRequest*>* request_order_; | 110 std::vector<TestSocketRequest*>* request_order_; |
| 120 TestCompletionCallback callback_; | 111 TestCompletionCallback callback_; |
| 121 }; | 112 }; |
| 122 | 113 |
| 123 int TestSocketRequest::completion_count = 0; | 114 size_t TestSocketRequest::completion_count = 0; |
| 124 | 115 |
| 125 class TestConnectJob : public ConnectJob { | 116 class TestConnectJob : public ConnectJob { |
| 126 public: | 117 public: |
| 127 enum JobType { | 118 enum JobType { |
| 128 kMockJob, | 119 kMockJob, |
| 129 kMockFailingJob, | 120 kMockFailingJob, |
| 130 kMockPendingJob, | 121 kMockPendingJob, |
| 131 kMockPendingFailingJob, | 122 kMockPendingFailingJob, |
| 132 }; | 123 }; |
| 133 | 124 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 | 214 |
| 224 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); | 215 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); |
| 225 }; | 216 }; |
| 226 | 217 |
| 227 class TestClientSocketPool : public ClientSocketPool { | 218 class TestClientSocketPool : public ClientSocketPool { |
| 228 public: | 219 public: |
| 229 TestClientSocketPool( | 220 TestClientSocketPool( |
| 230 int max_sockets_per_group, | 221 int max_sockets_per_group, |
| 231 ClientSocketPoolBase::ConnectJobFactory* connect_job_factory) | 222 ClientSocketPoolBase::ConnectJobFactory* connect_job_factory) |
| 232 : base_(new ClientSocketPoolBase( | 223 : base_(new ClientSocketPoolBase( |
| 233 kMaxSocketsPerGroup, connect_job_factory)) {} | 224 max_sockets_per_group, connect_job_factory)) {} |
| 234 | 225 |
| 235 virtual int RequestSocket( | 226 virtual int RequestSocket( |
| 236 const std::string& group_name, | 227 const std::string& group_name, |
| 237 const HostResolver::RequestInfo& resolve_info, | 228 const HostResolver::RequestInfo& resolve_info, |
| 238 int priority, | 229 int priority, |
| 239 ClientSocketHandle* handle, | 230 ClientSocketHandle* handle, |
| 240 CompletionCallback* callback) { | 231 CompletionCallback* callback) { |
| 241 return base_->RequestSocket( | 232 return base_->RequestSocket( |
| 242 group_name, resolve_info, priority, handle, callback); | 233 group_name, resolve_info, priority, handle, callback); |
| 243 } | 234 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 262 | 253 |
| 263 virtual int IdleSocketCountInGroup(const std::string& group_name) const { | 254 virtual int IdleSocketCountInGroup(const std::string& group_name) const { |
| 264 return base_->IdleSocketCountInGroup(group_name); | 255 return base_->IdleSocketCountInGroup(group_name); |
| 265 } | 256 } |
| 266 | 257 |
| 267 virtual LoadState GetLoadState(const std::string& group_name, | 258 virtual LoadState GetLoadState(const std::string& group_name, |
| 268 const ClientSocketHandle* handle) const { | 259 const ClientSocketHandle* handle) const { |
| 269 return base_->GetLoadState(group_name, handle); | 260 return base_->GetLoadState(group_name, handle); |
| 270 } | 261 } |
| 271 | 262 |
| 263 int MaxSocketsPerGroup() const { |
| 264 return base_->max_sockets_per_group(); |
| 265 } |
| 266 |
| 272 private: | 267 private: |
| 273 const scoped_refptr<ClientSocketPoolBase> base_; | 268 const scoped_refptr<ClientSocketPoolBase> base_; |
| 274 | 269 |
| 275 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); | 270 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); |
| 276 }; | 271 }; |
| 277 | 272 |
| 278 class ClientSocketPoolBaseTest : public testing::Test { | 273 class ClientSocketPoolBaseTest : public testing::Test { |
| 279 protected: | 274 protected: |
| 280 ClientSocketPoolBaseTest() | 275 ClientSocketPoolBaseTest() |
| 281 : ignored_request_info_("ignored", 80), | 276 : ignored_request_info_("ignored", 80), |
| 282 connect_job_factory_( | 277 connect_job_factory_( |
| 283 new TestConnectJobFactory(&client_socket_factory_)), | 278 new TestConnectJobFactory(&client_socket_factory_)) {} |
| 284 pool_(new TestClientSocketPool(kMaxSocketsPerGroup, | 279 |
| 285 connect_job_factory_)) {} | 280 void CreatePool(int max_sockets_per_group) { |
| 281 DCHECK(!pool_.get()); |
| 282 pool_ = new TestClientSocketPool(max_sockets_per_group, |
| 283 connect_job_factory_); |
| 284 } |
| 286 | 285 |
| 287 virtual void SetUp() { | 286 virtual void SetUp() { |
| 288 TestSocketRequest::completion_count = 0; | 287 TestSocketRequest::completion_count = 0; |
| 289 } | 288 } |
| 290 | 289 |
| 291 virtual void TearDown() { | 290 virtual void TearDown() { |
| 292 // The tests often call Reset() on handles at the end which may post | 291 // The tests often call Reset() on handles at the end which may post |
| 293 // DoReleaseSocket() tasks. | 292 // DoReleaseSocket() tasks. |
| 294 MessageLoop::current()->RunAllPending(); | 293 MessageLoop::current()->RunAllPending(); |
| 295 } | 294 } |
| 296 | 295 |
| 297 void CreateConnections(scoped_ptr<TestSocketRequest>* reqs, size_t count) { | 296 int StartRequest(const std::string& group_name, int priority) { |
| 298 for (size_t i = 0; i < count; ++i) | 297 DCHECK(pool_.get()); |
| 299 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 298 TestSocketRequest* request = new TestSocketRequest(pool_.get(), |
| 299 &request_order_); |
| 300 requests_.push_back(request); |
| 301 int rv = request->handle.Init(group_name, ignored_request_info_, priority, |
| 302 request); |
| 303 if (rv != ERR_IO_PENDING) |
| 304 request_order_.push_back(request); |
| 305 return rv; |
| 306 } |
| 300 | 307 |
| 301 // Create connections or queue up requests. | 308 static const int kIndexOutOfBounds; |
| 302 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 309 static const int kRequestNotFound; |
| 303 int rv = reqs[i]->handle.Init("a", ignored_request_info_, | |
| 304 kDefaultPriority, reqs[i].get()); | |
| 305 EXPECT_EQ(OK, rv); | |
| 306 request_order_.push_back(reqs[i].get()); | |
| 307 } | |
| 308 | 310 |
| 309 // The rest are pending since we've used all active sockets. | 311 int GetOrderOfRequest(size_t index) { |
| 310 for (int i = 0; i < kNumPendingRequests; ++i) { | 312 index--; |
| 311 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | 313 if (index >= requests_.size()) |
| 312 "a", ignored_request_info_, kPriorities[i], | 314 return kIndexOutOfBounds; |
| 313 reqs[kMaxSocketsPerGroup + i].get()); | 315 |
| 314 EXPECT_EQ(ERR_IO_PENDING, rv); | 316 for (size_t i = 0; i < request_order_.size(); i++) |
| 315 } | 317 if (requests_[index] == request_order_[i]) |
| 318 return i + 1; |
| 319 |
| 320 return kRequestNotFound; |
| 316 } | 321 } |
| 317 | 322 |
| 318 enum KeepAlive { | 323 enum KeepAlive { |
| 319 KEEP_ALIVE, | 324 KEEP_ALIVE, |
| 320 NO_KEEP_ALIVE, | 325 NO_KEEP_ALIVE, |
| 321 }; | 326 }; |
| 322 | 327 |
| 323 void ReleaseAllConnections(scoped_ptr<TestSocketRequest>* reqs, | 328 void ReleaseAllConnections(KeepAlive keep_alive) { |
| 324 size_t count, KeepAlive keep_alive) { | |
| 325 bool released_one; | 329 bool released_one; |
| 326 do { | 330 do { |
| 327 released_one = false; | 331 released_one = false; |
| 328 for (size_t i = 0; i < count; ++i) { | 332 ScopedVector<TestSocketRequest>::iterator i; |
| 329 if (reqs[i]->handle.is_initialized()) { | 333 for (i = requests_.begin(); i != requests_.end(); ++i) { |
| 334 if ((*i)->handle.is_initialized()) { |
| 330 if (keep_alive == NO_KEEP_ALIVE) | 335 if (keep_alive == NO_KEEP_ALIVE) |
| 331 reqs[i]->handle.socket()->Disconnect(); | 336 (*i)->handle.socket()->Disconnect(); |
| 332 reqs[i]->handle.Reset(); | 337 (*i)->handle.Reset(); |
| 333 MessageLoop::current()->RunAllPending(); | 338 MessageLoop::current()->RunAllPending(); |
| 334 released_one = true; | 339 released_one = true; |
| 335 } | 340 } |
| 336 } | 341 } |
| 337 } while (released_one); | 342 } while (released_one); |
| 338 } | 343 } |
| 339 | 344 |
| 340 HostResolver::RequestInfo ignored_request_info_; | 345 HostResolver::RequestInfo ignored_request_info_; |
| 341 MockClientSocketFactory client_socket_factory_; | 346 MockClientSocketFactory client_socket_factory_; |
| 342 TestConnectJobFactory* const connect_job_factory_; | 347 TestConnectJobFactory* const connect_job_factory_; |
| 343 scoped_refptr<ClientSocketPool> pool_; | 348 scoped_refptr<TestClientSocketPool> pool_; |
| 349 ScopedVector<TestSocketRequest> requests_; |
| 344 std::vector<TestSocketRequest*> request_order_; | 350 std::vector<TestSocketRequest*> request_order_; |
| 345 }; | 351 }; |
| 346 | 352 |
| 353 // static |
| 354 const int ClientSocketPoolBaseTest::kIndexOutOfBounds = -1; |
| 355 |
| 356 // static |
| 357 const int ClientSocketPoolBaseTest::kRequestNotFound = -2; |
| 358 |
| 347 TEST_F(ClientSocketPoolBaseTest, Basic) { | 359 TEST_F(ClientSocketPoolBaseTest, Basic) { |
| 360 CreatePool(kDefaultMaxSocketsPerGroup); |
| 361 |
| 348 TestCompletionCallback callback; | 362 TestCompletionCallback callback; |
| 349 ClientSocketHandle handle(pool_.get()); | 363 ClientSocketHandle handle(pool_.get()); |
| 350 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority, | 364 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority, |
| 351 &callback)); | 365 &callback)); |
| 352 EXPECT_TRUE(handle.is_initialized()); | 366 EXPECT_TRUE(handle.is_initialized()); |
| 353 EXPECT_TRUE(handle.socket()); | 367 EXPECT_TRUE(handle.socket()); |
| 354 handle.Reset(); | 368 handle.Reset(); |
| 355 } | 369 } |
| 356 | 370 |
| 357 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { | 371 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { |
| 372 CreatePool(kDefaultMaxSocketsPerGroup); |
| 373 |
| 358 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | 374 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); |
| 359 TestSocketRequest req(pool_.get(), &request_order_); | 375 TestSocketRequest req(pool_.get(), &request_order_); |
| 360 EXPECT_EQ(ERR_CONNECTION_FAILED, | 376 EXPECT_EQ(ERR_CONNECTION_FAILED, |
| 361 req.handle.Init("a", ignored_request_info_, | 377 req.handle.Init("a", ignored_request_info_, |
| 362 kDefaultPriority, &req)); | 378 kDefaultPriority, &req)); |
| 363 } | 379 } |
| 364 | 380 |
| 365 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { | 381 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { |
| 366 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 382 CreatePool(kDefaultMaxSocketsPerGroup); |
| 367 | 383 |
| 368 CreateConnections(reqs, arraysize(reqs)); | 384 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
| 369 ReleaseAllConnections(reqs, arraysize(reqs), KEEP_ALIVE); | 385 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
| 386 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1)); |
| 387 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3)); |
| 388 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4)); |
| 389 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2)); |
| 390 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1)); |
| 370 | 391 |
| 371 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); | 392 ReleaseAllConnections(KEEP_ALIVE); |
| 372 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | |
| 373 | 393 |
| 374 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 394 EXPECT_EQ(kDefaultMaxSocketsPerGroup, |
| 375 EXPECT_EQ(request_order_[i], reqs[i].get()) << | 395 client_socket_factory_.allocation_count()); |
| 376 "Request " << i << " was not in order."; | 396 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, |
| 377 } | 397 TestSocketRequest::completion_count); |
| 378 | 398 |
| 379 for (int i = 0; i < kNumPendingRequests - 1; ++i) { | 399 EXPECT_EQ(1, GetOrderOfRequest(1)); |
| 380 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i]; | 400 EXPECT_EQ(2, GetOrderOfRequest(2)); |
| 381 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue], | 401 EXPECT_EQ(6, GetOrderOfRequest(3)); |
| 382 reqs[kMaxSocketsPerGroup + i].get()) << | 402 EXPECT_EQ(4, GetOrderOfRequest(4)); |
| 383 "Request " << kMaxSocketsPerGroup + i << " was not in order."; | 403 EXPECT_EQ(3, GetOrderOfRequest(5)); |
| 384 } | 404 EXPECT_EQ(5, GetOrderOfRequest(6)); |
| 385 | 405 EXPECT_EQ(7, GetOrderOfRequest(7)); |
| 386 EXPECT_EQ(request_order_[arraysize(reqs) - 1], | |
| 387 reqs[arraysize(reqs) - 1].get()) << | |
| 388 "The last request with priority 1 should not have been inserted " | |
| 389 "earlier into the queue."; | |
| 390 } | 406 } |
| 391 | 407 |
| 392 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { | 408 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { |
| 393 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 409 CreatePool(kDefaultMaxSocketsPerGroup); |
| 394 | 410 |
| 395 CreateConnections(reqs, arraysize(reqs)); | 411 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
| 396 ReleaseAllConnections(reqs, arraysize(reqs), NO_KEEP_ALIVE); | 412 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
| 413 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1)); |
| 414 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3)); |
| 415 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4)); |
| 416 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2)); |
| 417 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1)); |
| 397 | 418 |
| 398 for (int i = kMaxSocketsPerGroup; i < kNumRequests; ++i) | 419 ReleaseAllConnections(NO_KEEP_ALIVE); |
| 399 EXPECT_EQ(OK, reqs[i]->WaitForResult()); | |
| 400 | 420 |
| 401 EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count()); | 421 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) |
| 402 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 422 EXPECT_EQ(OK, requests_[i]->WaitForResult()); |
| 423 |
| 424 EXPECT_EQ(static_cast<int>(requests_.size()), |
| 425 client_socket_factory_.allocation_count()); |
| 426 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, |
| 427 TestSocketRequest::completion_count); |
| 403 } | 428 } |
| 404 | 429 |
| 405 // This test will start up a RequestSocket() and then immediately Cancel() it. | 430 // This test will start up a RequestSocket() and then immediately Cancel() it. |
| 406 // The pending connect job will be cancelled and should not call back into | 431 // The pending connect job will be cancelled and should not call back into |
| 407 // ClientSocketPoolBase. | 432 // ClientSocketPoolBase. |
| 408 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { | 433 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { |
| 434 CreatePool(kDefaultMaxSocketsPerGroup); |
| 435 |
| 409 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 436 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 410 TestSocketRequest req(pool_.get(), &request_order_); | 437 TestSocketRequest req(pool_.get(), &request_order_); |
| 411 EXPECT_EQ(ERR_IO_PENDING, | 438 EXPECT_EQ(ERR_IO_PENDING, |
| 412 req.handle.Init("a", ignored_request_info_, | 439 req.handle.Init("a", ignored_request_info_, |
| 413 kDefaultPriority, &req)); | 440 kDefaultPriority, &req)); |
| 414 req.handle.Reset(); | 441 req.handle.Reset(); |
| 415 } | 442 } |
| 416 | 443 |
| 417 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { | 444 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { |
| 445 CreatePool(kDefaultMaxSocketsPerGroup); |
| 446 |
| 418 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 447 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 419 TestSocketRequest req(pool_.get(), &request_order_); | 448 TestSocketRequest req(pool_.get(), &request_order_); |
| 420 TestSocketRequest req2(pool_.get(), &request_order_); | 449 TestSocketRequest req2(pool_.get(), &request_order_); |
| 421 | 450 |
| 422 EXPECT_EQ(ERR_IO_PENDING, | 451 EXPECT_EQ(ERR_IO_PENDING, |
| 423 req.handle.Init("a", ignored_request_info_, | 452 req.handle.Init("a", ignored_request_info_, |
| 424 kDefaultPriority, &req)); | 453 kDefaultPriority, &req)); |
| 425 EXPECT_EQ(ERR_IO_PENDING, | 454 EXPECT_EQ(ERR_IO_PENDING, |
| 426 req2.handle.Init("a", ignored_request_info_, | 455 req2.handle.Init("a", ignored_request_info_, |
| 427 kDefaultPriority, &req2)); | 456 kDefaultPriority, &req2)); |
| 428 | 457 |
| 429 req.handle.Reset(); | 458 req.handle.Reset(); |
| 430 | 459 |
| 431 EXPECT_EQ(OK, req2.WaitForResult()); | 460 EXPECT_EQ(OK, req2.WaitForResult()); |
| 432 req2.handle.Reset(); | 461 req2.handle.Reset(); |
| 433 } | 462 } |
| 434 | 463 |
| 435 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { | 464 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { |
| 465 CreatePool(kDefaultMaxSocketsPerGroup); |
| 466 |
| 436 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 467 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 437 ClientSocketHandle handle(pool_.get()); | 468 ClientSocketHandle handle(pool_.get()); |
| 438 TestCompletionCallback callback; | 469 TestCompletionCallback callback; |
| 439 TestSocketRequest req(pool_.get(), &request_order_); | 470 TestSocketRequest req(pool_.get(), &request_order_); |
| 440 | 471 |
| 441 EXPECT_EQ(ERR_IO_PENDING, | 472 EXPECT_EQ(ERR_IO_PENDING, |
| 442 handle.Init("a", ignored_request_info_, | 473 handle.Init("a", ignored_request_info_, |
| 443 kDefaultPriority, &callback)); | 474 kDefaultPriority, &callback)); |
| 444 | 475 |
| 445 handle.Reset(); | 476 handle.Reset(); |
| 446 | 477 |
| 447 TestCompletionCallback callback2; | 478 TestCompletionCallback callback2; |
| 448 EXPECT_EQ(ERR_IO_PENDING, | 479 EXPECT_EQ(ERR_IO_PENDING, |
| 449 handle.Init("a", ignored_request_info_, | 480 handle.Init("a", ignored_request_info_, |
| 450 kDefaultPriority, &callback2)); | 481 kDefaultPriority, &callback2)); |
| 451 | 482 |
| 452 EXPECT_EQ(OK, callback2.WaitForResult()); | 483 EXPECT_EQ(OK, callback2.WaitForResult()); |
| 453 EXPECT_FALSE(callback.have_result()); | 484 EXPECT_FALSE(callback.have_result()); |
| 454 | 485 |
| 455 handle.Reset(); | 486 handle.Reset(); |
| 456 } | 487 } |
| 457 | 488 |
| 458 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { | 489 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { |
| 459 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 490 CreatePool(kDefaultMaxSocketsPerGroup); |
| 460 | 491 |
| 461 CreateConnections(reqs, arraysize(reqs)); | 492 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
| 493 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
| 494 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1)); |
| 495 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3)); |
| 496 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4)); |
| 497 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2)); |
| 498 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1)); |
| 462 | 499 |
| 463 // Cancel a request. | 500 // Cancel a request. |
| 464 size_t index_to_cancel = kMaxSocketsPerGroup + 2; | 501 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2; |
| 465 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); | 502 EXPECT_FALSE(requests_[index_to_cancel]->handle.is_initialized()); |
| 466 reqs[index_to_cancel]->handle.Reset(); | 503 requests_[index_to_cancel]->handle.Reset(); |
| 467 | 504 |
| 468 ReleaseAllConnections(reqs, arraysize(reqs), KEEP_ALIVE); | 505 ReleaseAllConnections(KEEP_ALIVE); |
| 469 | 506 |
| 470 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); | 507 EXPECT_EQ(kDefaultMaxSocketsPerGroup, |
| 471 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count); | 508 client_socket_factory_.allocation_count()); |
| 509 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1, |
| 510 TestSocketRequest::completion_count); |
| 472 | 511 |
| 473 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 512 EXPECT_EQ(1, GetOrderOfRequest(1)); |
| 474 EXPECT_EQ(request_order_[i], reqs[i].get()) << | 513 EXPECT_EQ(2, GetOrderOfRequest(2)); |
| 475 "Request " << i << " was not in order."; | 514 EXPECT_EQ(5, GetOrderOfRequest(3)); |
| 476 } | 515 EXPECT_EQ(3, GetOrderOfRequest(4)); |
| 477 | 516 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request. |
| 478 for (int i = 0; i < kNumPendingRequests - 1; ++i) { | 517 EXPECT_EQ(4, GetOrderOfRequest(6)); |
| 479 if (i == 2) continue; | 518 EXPECT_EQ(6, GetOrderOfRequest(7)); |
| 480 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i]; | |
| 481 if (kPriorities[i] < kPriorities[index_to_cancel - kMaxSocketsPerGroup]) | |
| 482 index_in_queue--; | |
| 483 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue], | |
| 484 reqs[kMaxSocketsPerGroup + i].get()) << | |
| 485 "Request " << kMaxSocketsPerGroup + i << " was not in order."; | |
| 486 } | |
| 487 | |
| 488 EXPECT_EQ(request_order_[arraysize(reqs) - 2], | |
| 489 reqs[arraysize(reqs) - 1].get()) << | |
| 490 "The last request with priority 1 should not have been inserted " | |
| 491 "earlier into the queue."; | |
| 492 } | 519 } |
| 493 | 520 |
| 494 class RequestSocketCallback : public CallbackRunner< Tuple1<int> > { | 521 class RequestSocketCallback : public CallbackRunner< Tuple1<int> > { |
| 495 public: | 522 public: |
| 496 RequestSocketCallback(ClientSocketHandle* handle, | 523 RequestSocketCallback(ClientSocketHandle* handle, |
| 497 TestConnectJobFactory* test_connect_job_factory, | 524 TestConnectJobFactory* test_connect_job_factory, |
| 498 TestConnectJob::JobType next_job_type) | 525 TestConnectJob::JobType next_job_type) |
| 499 : handle_(handle), | 526 : handle_(handle), |
| 500 within_callback_(false), | 527 within_callback_(false), |
| 501 test_connect_job_factory_(test_connect_job_factory), | 528 test_connect_job_factory_(test_connect_job_factory), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 532 | 559 |
| 533 private: | 560 private: |
| 534 ClientSocketHandle* const handle_; | 561 ClientSocketHandle* const handle_; |
| 535 bool within_callback_; | 562 bool within_callback_; |
| 536 TestConnectJobFactory* const test_connect_job_factory_; | 563 TestConnectJobFactory* const test_connect_job_factory_; |
| 537 TestConnectJob::JobType next_job_type_; | 564 TestConnectJob::JobType next_job_type_; |
| 538 TestCompletionCallback callback_; | 565 TestCompletionCallback callback_; |
| 539 }; | 566 }; |
| 540 | 567 |
| 541 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { | 568 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
| 569 CreatePool(kDefaultMaxSocketsPerGroup); |
| 570 |
| 542 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 571 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 543 ClientSocketHandle handle(pool_.get()); | 572 ClientSocketHandle handle(pool_.get()); |
| 544 RequestSocketCallback callback( | 573 RequestSocketCallback callback( |
| 545 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); | 574 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); |
| 546 int rv = handle.Init( | 575 int rv = handle.Init( |
| 547 "a", ignored_request_info_, kDefaultPriority, &callback); | 576 "a", ignored_request_info_, kDefaultPriority, &callback); |
| 548 ASSERT_EQ(ERR_IO_PENDING, rv); | 577 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 549 | 578 |
| 550 EXPECT_EQ(OK, callback.WaitForResult()); | 579 EXPECT_EQ(OK, callback.WaitForResult()); |
| 551 handle.Reset(); | 580 handle.Reset(); |
| 552 } | 581 } |
| 553 | 582 |
| 554 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { | 583 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
| 584 CreatePool(kDefaultMaxSocketsPerGroup); |
| 585 |
| 555 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 586 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 556 ClientSocketHandle handle(pool_.get()); | 587 ClientSocketHandle handle(pool_.get()); |
| 557 RequestSocketCallback callback( | 588 RequestSocketCallback callback( |
| 558 &handle, connect_job_factory_, TestConnectJob::kMockJob); | 589 &handle, connect_job_factory_, TestConnectJob::kMockJob); |
| 559 int rv = handle.Init( | 590 int rv = handle.Init( |
| 560 "a", ignored_request_info_, kDefaultPriority, &callback); | 591 "a", ignored_request_info_, kDefaultPriority, &callback); |
| 561 ASSERT_EQ(ERR_IO_PENDING, rv); | 592 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 562 | 593 |
| 563 EXPECT_EQ(OK, callback.WaitForResult()); | 594 EXPECT_EQ(OK, callback.WaitForResult()); |
| 564 handle.Reset(); | 595 handle.Reset(); |
| 565 } | 596 } |
| 566 | 597 |
| 567 // Make sure that pending requests get serviced after active requests get | 598 // Make sure that pending requests get serviced after active requests get |
| 568 // cancelled. | 599 // cancelled. |
| 569 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { | 600 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { |
| 601 CreatePool(kDefaultMaxSocketsPerGroup); |
| 602 |
| 570 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 603 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 571 | 604 |
| 572 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 605 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 606 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 607 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 608 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 609 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 610 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 611 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 573 | 612 |
| 574 // Queue up all the requests | 613 // Now, kDefaultMaxSocketsPerGroup requests should be active. |
| 575 for (size_t i = 0; i < arraysize(reqs); ++i) { | 614 // Let's cancel them. |
| 576 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 615 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) { |
| 577 int rv = reqs[i]->handle.Init("a", ignored_request_info_, | 616 ASSERT_FALSE(requests_[i]->handle.is_initialized()); |
| 578 kDefaultPriority, reqs[i].get()); | 617 requests_[i]->handle.Reset(); |
| 579 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 580 } | 618 } |
| 581 | 619 |
| 582 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. | |
| 583 for (int i = 0; i < kMaxSocketsPerGroup; ++i) | |
| 584 reqs[i]->handle.Reset(); | |
| 585 | |
| 586 // Let's wait for the rest to complete now. | 620 // Let's wait for the rest to complete now. |
| 587 for (size_t i = kMaxSocketsPerGroup; i < arraysize(reqs); ++i) { | 621 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) { |
| 588 EXPECT_EQ(OK, reqs[i]->WaitForResult()); | 622 EXPECT_EQ(OK, requests_[i]->WaitForResult()); |
| 589 reqs[i]->handle.Reset(); | 623 requests_[i]->handle.Reset(); |
| 590 } | 624 } |
| 591 | 625 |
| 592 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 626 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, |
| 627 TestSocketRequest::completion_count); |
| 593 } | 628 } |
| 594 | 629 |
| 595 // Make sure that pending requests get serviced after active requests fail. | 630 // Make sure that pending requests get serviced after active requests fail. |
| 596 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { | 631 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { |
| 632 CreatePool(kDefaultMaxSocketsPerGroup); |
| 633 |
| 597 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | 634 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
| 598 | 635 |
| 599 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup * 2 + 1]; | 636 scoped_ptr<TestSocketRequest> reqs[kDefaultMaxSocketsPerGroup * 2 + 1]; |
| 600 | 637 |
| 601 // Queue up all the requests | 638 // Queue up all the requests |
| 602 for (size_t i = 0; i < arraysize(reqs); ++i) { | 639 for (size_t i = 0; i < arraysize(reqs); ++i) { |
| 603 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 640 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
| 604 int rv = reqs[i]->handle.Init("a", ignored_request_info_, | 641 int rv = reqs[i]->handle.Init("a", ignored_request_info_, |
| 605 kDefaultPriority, reqs[i].get()); | 642 kDefaultPriority, reqs[i].get()); |
| 606 EXPECT_EQ(ERR_IO_PENDING, rv); | 643 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 607 } | 644 } |
| 608 | 645 |
| 609 for (size_t i = 0; i < arraysize(reqs); ++i) | 646 for (size_t i = 0; i < arraysize(reqs); ++i) |
| 610 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); | 647 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); |
| 611 } | 648 } |
| 612 | 649 |
| 613 // A pending asynchronous job completes, which will free up a socket slot. The | 650 // A pending asynchronous job completes, which will free up a socket slot. The |
| 614 // next job finishes synchronously. The callback for the asynchronous job | 651 // next job finishes synchronously. The callback for the asynchronous job |
| 615 // should be first though. | 652 // should be first though. |
| 616 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { | 653 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { |
| 654 CreatePool(kDefaultMaxSocketsPerGroup); |
| 655 |
| 617 // First two jobs are async. | 656 // First two jobs are async. |
| 618 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | 657 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
| 619 | 658 |
| 620 // Start job 1 (async error). | 659 // Start job 1 (async error). |
| 621 TestSocketRequest req1(pool_.get(), &request_order_); | 660 TestSocketRequest req1(pool_.get(), &request_order_); |
| 622 int rv = req1.handle.Init("a", ignored_request_info_, | 661 int rv = req1.handle.Init("a", ignored_request_info_, |
| 623 kDefaultPriority, &req1); | 662 kDefaultPriority, &req1); |
| 624 EXPECT_EQ(ERR_IO_PENDING, rv); | 663 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 625 | 664 |
| 626 // Start job 2 (async error). | 665 // Start job 2 (async error). |
| (...skipping 19 matching lines...) Expand all Loading... |
| 646 // requests queue, so it starts up job 3 for request 3. This job | 685 // requests queue, so it starts up job 3 for request 3. This job |
| 647 // synchronously succeeds, so the request order is 1, 3, 2. | 686 // synchronously succeeds, so the request order is 1, 3, 2. |
| 648 EXPECT_EQ(&req1, request_order_[0]); | 687 EXPECT_EQ(&req1, request_order_[0]); |
| 649 EXPECT_EQ(&req2, request_order_[2]); | 688 EXPECT_EQ(&req2, request_order_[2]); |
| 650 EXPECT_EQ(&req3, request_order_[1]); | 689 EXPECT_EQ(&req3, request_order_[1]); |
| 651 } | 690 } |
| 652 | 691 |
| 653 } // namespace | 692 } // namespace |
| 654 | 693 |
| 655 } // namespace net | 694 } // namespace net |
| OLD | NEW |