OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/logging.h" |
12 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
13 #include "base/memory/scoped_vector.h" | 14 #include "base/memory/scoped_vector.h" |
14 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
15 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
16 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
17 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
19 #include "base/threading/platform_thread.h" | 20 #include "base/threading/platform_thread.h" |
20 #include "base/values.h" | 21 #include "base/values.h" |
21 #include "net/base/load_timing_info.h" | 22 #include "net/base/load_timing_info.h" |
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1420 EXPECT_EQ(3, GetOrderOfRequest(4)); | 1421 EXPECT_EQ(3, GetOrderOfRequest(4)); |
1421 EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, | 1422 EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, |
1422 GetOrderOfRequest(5)); // Canceled request. | 1423 GetOrderOfRequest(5)); // Canceled request. |
1423 EXPECT_EQ(4, GetOrderOfRequest(6)); | 1424 EXPECT_EQ(4, GetOrderOfRequest(6)); |
1424 EXPECT_EQ(6, GetOrderOfRequest(7)); | 1425 EXPECT_EQ(6, GetOrderOfRequest(7)); |
1425 | 1426 |
1426 // Make sure we test order of all requests made. | 1427 // Make sure we test order of all requests made. |
1427 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(8)); | 1428 EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(8)); |
1428 } | 1429 } |
1429 | 1430 |
1430 class RequestSocketCallback : public TestCompletionCallbackBase { | 1431 // Function to be used as a callback on socket request completion. It first |
1431 public: | 1432 // disconnects the successfully connected socket from the first request, and |
1432 RequestSocketCallback(ClientSocketHandle* handle, | 1433 // then reuses the ClientSocketHandle to request another socket. |
1433 TestClientSocketPool* pool, | 1434 // |
1434 TestConnectJobFactory* test_connect_job_factory, | 1435 // |nested_callback| is called with the result of the second socket request. |
1435 TestConnectJob::JobType next_job_type) | 1436 void RequestSocketOnComplete(ClientSocketHandle* handle, |
1436 : handle_(handle), | 1437 TestClientSocketPool* pool, |
1437 pool_(pool), | 1438 TestConnectJobFactory* test_connect_job_factory, |
1438 within_callback_(false), | 1439 TestConnectJob::JobType next_job_type, |
1439 test_connect_job_factory_(test_connect_job_factory), | 1440 const CompletionCallback& nested_callback, |
1440 next_job_type_(next_job_type), | 1441 int first_request_result) { |
1441 callback_(base::Bind(&RequestSocketCallback::OnComplete, | 1442 EXPECT_EQ(OK, first_request_result); |
1442 base::Unretained(this))) { | 1443 |
| 1444 test_connect_job_factory->set_job_type(next_job_type); |
| 1445 |
| 1446 // Don't allow reuse of the socket. Disconnect it and then release it. |
| 1447 if (handle->socket()) |
| 1448 handle->socket()->Disconnect(); |
| 1449 handle->Reset(); |
| 1450 |
| 1451 scoped_refptr<TestSocketParams> params( |
| 1452 new TestSocketParams(false /* ignore_limits */)); |
| 1453 TestCompletionCallback callback; |
| 1454 int rv = |
| 1455 handle->Init("a", params, LOWEST, nested_callback, pool, BoundNetLog()); |
| 1456 if (rv != ERR_IO_PENDING) { |
| 1457 DCHECK_EQ(TestConnectJob::kMockJob, next_job_type); |
| 1458 nested_callback.Run(rv); |
| 1459 } else { |
| 1460 DCHECK_EQ(TestConnectJob::kMockPendingJob, next_job_type); |
1443 } | 1461 } |
| 1462 } |
1444 | 1463 |
1445 ~RequestSocketCallback() override {} | 1464 // Tests the case where a second socket is requested in a completion callback, |
1446 | 1465 // and the second socket connects asynchronously. Reuses the same |
1447 const CompletionCallback& callback() const { return callback_; } | 1466 // ClientSocketHandle for the second socket, after disconnecting the first. |
1448 | |
1449 private: | |
1450 void OnComplete(int result) { | |
1451 SetResult(result); | |
1452 ASSERT_EQ(OK, result); | |
1453 | |
1454 if (!within_callback_) { | |
1455 test_connect_job_factory_->set_job_type(next_job_type_); | |
1456 | |
1457 // Don't allow reuse of the socket. Disconnect it and then release it and | |
1458 // run through the MessageLoop once to get it completely released. | |
1459 handle_->socket()->Disconnect(); | |
1460 handle_->Reset(); | |
1461 { | |
1462 // TODO: Resolve conflicting intentions of stopping recursion with the | |
1463 // |!within_callback_| test (above) and the call to |RunUntilIdle()| | |
1464 // below. http://crbug.com/114130. | |
1465 base::MessageLoop::ScopedNestableTaskAllower allow( | |
1466 base::MessageLoop::current()); | |
1467 base::MessageLoop::current()->RunUntilIdle(); | |
1468 } | |
1469 within_callback_ = true; | |
1470 TestCompletionCallback next_job_callback; | |
1471 scoped_refptr<TestSocketParams> params( | |
1472 new TestSocketParams(false /* ignore_limits */)); | |
1473 int rv = handle_->Init("a", | |
1474 params, | |
1475 DEFAULT_PRIORITY, | |
1476 next_job_callback.callback(), | |
1477 pool_, | |
1478 BoundNetLog()); | |
1479 switch (next_job_type_) { | |
1480 case TestConnectJob::kMockJob: | |
1481 EXPECT_EQ(OK, rv); | |
1482 break; | |
1483 case TestConnectJob::kMockPendingJob: | |
1484 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1485 | |
1486 // For pending jobs, wait for new socket to be created. This makes | |
1487 // sure there are no more pending operations nor any unclosed sockets | |
1488 // when the test finishes. | |
1489 // We need to give it a little bit of time to run, so that all the | |
1490 // operations that happen on timers (e.g. cleanup of idle | |
1491 // connections) can execute. | |
1492 { | |
1493 base::MessageLoop::ScopedNestableTaskAllower allow( | |
1494 base::MessageLoop::current()); | |
1495 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | |
1496 EXPECT_EQ(OK, next_job_callback.WaitForResult()); | |
1497 } | |
1498 break; | |
1499 default: | |
1500 FAIL() << "Unexpected job type: " << next_job_type_; | |
1501 break; | |
1502 } | |
1503 } | |
1504 } | |
1505 | |
1506 ClientSocketHandle* const handle_; | |
1507 TestClientSocketPool* const pool_; | |
1508 bool within_callback_; | |
1509 TestConnectJobFactory* const test_connect_job_factory_; | |
1510 TestConnectJob::JobType next_job_type_; | |
1511 CompletionCallback callback_; | |
1512 }; | |
1513 | |
1514 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { | 1467 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
1515 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | 1468 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
1516 | 1469 |
1517 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 1470 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
1518 ClientSocketHandle handle; | 1471 ClientSocketHandle handle; |
1519 RequestSocketCallback callback( | 1472 TestCompletionCallback second_result_callback; |
1520 &handle, pool_.get(), connect_job_factory_, | 1473 int rv = handle.Init( |
1521 TestConnectJob::kMockPendingJob); | 1474 "a", params_, DEFAULT_PRIORITY, |
1522 int rv = handle.Init("a", | 1475 base::Bind(&RequestSocketOnComplete, &handle, pool_.get(), |
1523 params_, | 1476 connect_job_factory_, TestConnectJob::kMockPendingJob, |
1524 DEFAULT_PRIORITY, | 1477 second_result_callback.callback()), |
1525 callback.callback(), | 1478 pool_.get(), BoundNetLog()); |
1526 pool_.get(), | |
1527 BoundNetLog()); | |
1528 ASSERT_EQ(ERR_IO_PENDING, rv); | 1479 ASSERT_EQ(ERR_IO_PENDING, rv); |
1529 | 1480 |
1530 EXPECT_EQ(OK, callback.WaitForResult()); | 1481 EXPECT_EQ(OK, second_result_callback.WaitForResult()); |
1531 } | 1482 } |
1532 | 1483 |
| 1484 // Tests the case where a second socket is requested in a completion callback, |
| 1485 // and the second socket connects synchronously. Reuses the same |
| 1486 // ClientSocketHandle for the second socket, after disconnecting the first. |
1533 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { | 1487 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
1534 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | 1488 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
1535 | 1489 |
1536 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 1490 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
1537 ClientSocketHandle handle; | 1491 ClientSocketHandle handle; |
1538 RequestSocketCallback callback( | 1492 TestCompletionCallback second_result_callback; |
1539 &handle, pool_.get(), connect_job_factory_, TestConnectJob::kMockJob); | 1493 int rv = handle.Init( |
1540 int rv = handle.Init("a", | 1494 "a", params_, DEFAULT_PRIORITY, |
1541 params_, | 1495 base::Bind(&RequestSocketOnComplete, &handle, pool_.get(), |
1542 DEFAULT_PRIORITY, | 1496 connect_job_factory_, TestConnectJob::kMockPendingJob, |
1543 callback.callback(), | 1497 second_result_callback.callback()), |
1544 pool_.get(), | 1498 pool_.get(), BoundNetLog()); |
1545 BoundNetLog()); | |
1546 ASSERT_EQ(ERR_IO_PENDING, rv); | 1499 ASSERT_EQ(ERR_IO_PENDING, rv); |
1547 | 1500 |
1548 EXPECT_EQ(OK, callback.WaitForResult()); | 1501 EXPECT_EQ(OK, second_result_callback.WaitForResult()); |
1549 } | 1502 } |
1550 | 1503 |
1551 // Make sure that pending requests get serviced after active requests get | 1504 // Make sure that pending requests get serviced after active requests get |
1552 // cancelled. | 1505 // cancelled. |
1553 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { | 1506 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { |
1554 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | 1507 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
1555 | 1508 |
1556 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 1509 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
1557 | 1510 |
1558 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); | 1511 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY)); |
(...skipping 2561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4120 request(1)->handle()->Reset(); | 4073 request(1)->handle()->Reset(); |
4121 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 4074 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
4122 | 4075 |
4123 EXPECT_EQ(OK, request(2)->WaitForResult()); | 4076 EXPECT_EQ(OK, request(2)->WaitForResult()); |
4124 EXPECT_FALSE(request(1)->have_result()); | 4077 EXPECT_FALSE(request(1)->have_result()); |
4125 } | 4078 } |
4126 | 4079 |
4127 } // namespace | 4080 } // namespace |
4128 | 4081 |
4129 } // namespace net | 4082 } // namespace net |
OLD | NEW |