Index: net/socket/client_socket_pool_base_unittest.cc |
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc |
index 33db24fa21d0db42debe74d9717e8254aebc19db..3a6b8936ab4f6c2c946553038db1d56a978370d2 100644 |
--- a/net/socket/client_socket_pool_base_unittest.cc |
+++ b/net/socket/client_socket_pool_base_unittest.cc |
@@ -94,7 +94,7 @@ class MockClientSocketFactory : public ClientSocketFactory { |
} |
virtual SSLClientSocket* CreateSSLClientSocket( |
- ClientSocket* transport_socket, |
+ ClientSocketHandle* transport_socket, |
const std::string& hostname, |
const SSLConfig& ssl_config) { |
NOTIMPLEMENTED(); |
@@ -122,6 +122,8 @@ class TestConnectJob : public ConnectJob { |
kMockAdvancingLoadStateJob, |
kMockRecoverableJob, |
kMockPendingRecoverableJob, |
+ kMockAdditionalErrorStateJob, |
+ kMockPendingAdditionalErrorStateJob, |
}; |
TestConnectJob(JobType job_type, |
@@ -136,7 +138,8 @@ class TestConnectJob : public ConnectJob { |
job_type_(job_type), |
client_socket_factory_(client_socket_factory), |
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
- load_state_(LOAD_STATE_IDLE) {} |
+ load_state_(LOAD_STATE_IDLE), |
+ store_additional_error_state_(false) {} |
void Signal() { |
DoConnect(waiting_success_, true /* async */, false /* recoverable */); |
@@ -144,6 +147,15 @@ class TestConnectJob : public ConnectJob { |
virtual LoadState GetLoadState() const { return load_state_; } |
+ virtual void GetAdditionalErrorState(ClientSocketHandle* handle) { |
+ if (store_additional_error_state_) { |
+ // Set all of the additional error state fields in some way. |
+ handle->set_is_ssl_error(true); |
+ scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders("")); |
+ handle->set_tunnel_auth_response_info(headers, NULL); |
+ } |
+ } |
+ |
private: |
// ConnectJob methods: |
@@ -216,6 +228,22 @@ class TestConnectJob : public ConnectJob { |
true /* recoverable */), |
2); |
return ERR_IO_PENDING; |
+ case kMockAdditionalErrorStateJob: |
+ store_additional_error_state_ = true; |
+ return DoConnect(false /* error */, false /* sync */, |
+ false /* recoverable */); |
+ case kMockPendingAdditionalErrorStateJob: |
+ set_load_state(LOAD_STATE_CONNECTING); |
+ store_additional_error_state_ = true; |
+ MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ method_factory_.NewRunnableMethod( |
+ &TestConnectJob::DoConnect, |
+ false /* error */, |
+ true /* async */, |
+ false /* recoverable */), |
+ 2); |
+ return ERR_IO_PENDING; |
default: |
NOTREACHED(); |
set_socket(NULL); |
@@ -263,6 +291,7 @@ class TestConnectJob : public ConnectJob { |
MockClientSocketFactory* const client_socket_factory_; |
ScopedRunnableMethodFactory<TestConnectJob> method_factory_; |
LoadState load_state_; |
+ bool store_additional_error_state_; |
DISALLOW_COPY_AND_ASSIGN(TestConnectJob); |
}; |
@@ -589,10 +618,16 @@ TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { |
CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
TestSocketRequest req(&request_order_, &completion_count_); |
+ // Set the additional error state members to ensure that they get cleared. |
+ req.handle()->set_is_ssl_error(true); |
+ scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders("")); |
+ req.handle()->set_tunnel_auth_response_info(headers, NULL); |
EXPECT_EQ(ERR_CONNECTION_FAILED, req.handle()->Init("a", params_, |
kDefaultPriority, &req, |
pool_, log.bound())); |
EXPECT_FALSE(req.handle()->socket()); |
+ EXPECT_FALSE(req.handle()->is_ssl_error()); |
+ EXPECT_TRUE(req.handle()->tunnel_auth_response_info().headers.get() == NULL); |
EXPECT_EQ(3u, log.entries().size()); |
EXPECT_TRUE(LogContainsBeginEvent( |
@@ -1345,10 +1380,16 @@ TEST_F(ClientSocketPoolBaseTest, |
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
TestSocketRequest req(&request_order_, &completion_count_); |
CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
+ // Set the additional error state members to ensure that they get cleared. |
+ req.handle()->set_is_ssl_error(true); |
+ scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders("")); |
+ req.handle()->set_tunnel_auth_response_info(headers, NULL); |
EXPECT_EQ(ERR_IO_PENDING, req.handle()->Init("a", params_, kDefaultPriority, |
&req, pool_, log.bound())); |
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle())); |
EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); |
+ EXPECT_FALSE(req.handle()->is_ssl_error()); |
+ EXPECT_TRUE(req.handle()->tunnel_auth_response_info().headers.get() == NULL); |
EXPECT_EQ(3u, log.entries().size()); |
EXPECT_TRUE(LogContainsBeginEvent( |
@@ -1541,6 +1582,39 @@ TEST_F(ClientSocketPoolBaseTest, AsyncRecoverable) { |
req.handle()->Reset(); |
} |
+TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateSynchronous) { |
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
+ connect_job_factory_->set_job_type( |
+ TestConnectJob::kMockAdditionalErrorStateJob); |
+ |
+ TestSocketRequest req(&request_order_, &completion_count_); |
+ EXPECT_EQ(ERR_CONNECTION_FAILED, req.handle()->Init("a", params_, |
+ kDefaultPriority, &req, |
+ pool_, BoundNetLog())); |
+ EXPECT_FALSE(req.handle()->is_initialized()); |
+ EXPECT_FALSE(req.handle()->socket()); |
+ EXPECT_TRUE(req.handle()->is_ssl_error()); |
+ EXPECT_FALSE(req.handle()->tunnel_auth_response_info().headers.get() == NULL); |
+ req.handle()->Reset(); |
+} |
+ |
+TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateAsynchronous) { |
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
+ |
+ connect_job_factory_->set_job_type( |
+ TestConnectJob::kMockPendingAdditionalErrorStateJob); |
+ TestSocketRequest req(&request_order_, &completion_count_); |
+ EXPECT_EQ(ERR_IO_PENDING, req.handle()->Init("a", params_, kDefaultPriority, |
+ &req, pool_, BoundNetLog())); |
+ EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle())); |
+ EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); |
+ EXPECT_FALSE(req.handle()->is_initialized()); |
+ EXPECT_FALSE(req.handle()->socket()); |
+ EXPECT_TRUE(req.handle()->is_ssl_error()); |
+ EXPECT_FALSE(req.handle()->tunnel_auth_response_info().headers.get() == NULL); |
+ req.handle()->Reset(); |
+} |
+ |
TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) { |
CreatePoolWithIdleTimeouts( |
kDefaultMaxSockets, kDefaultMaxSocketsPerGroup, |
@@ -1728,8 +1802,11 @@ TEST_F(ClientSocketPoolBaseTest, |
class TestReleasingSocketRequest : public CallbackRunner< Tuple1<int> > { |
public: |
- explicit TestReleasingSocketRequest(TestClientSocketPool* pool) |
- : pool_(pool) {} |
+ TestReleasingSocketRequest(TestClientSocketPool* pool, int expected_result, |
+ bool reset_releasing_handle) |
+ : pool_(pool), |
+ expected_result_(expected_result), |
+ reset_releasing_handle_(reset_releasing_handle) {} |
ClientSocketHandle* handle() { return &handle_; } |
@@ -1739,20 +1816,50 @@ class TestReleasingSocketRequest : public CallbackRunner< Tuple1<int> > { |
virtual void RunWithParams(const Tuple1<int>& params) { |
callback_.RunWithParams(params); |
- handle_.Reset(); |
+ if (reset_releasing_handle_) |
+ handle_.Reset(); |
scoped_refptr<TestSocketParams> con_params = new TestSocketParams(); |
- EXPECT_EQ(ERR_IO_PENDING, handle2_.Init("a", con_params, kDefaultPriority, |
- &callback2_, pool_, BoundNetLog())); |
+ EXPECT_EQ(expected_result_, handle2_.Init("a", con_params, kDefaultPriority, |
+ &callback2_, pool_, |
+ BoundNetLog())); |
} |
private: |
scoped_refptr<TestClientSocketPool> pool_; |
+ int expected_result_; |
+ bool reset_releasing_handle_; |
ClientSocketHandle handle_; |
ClientSocketHandle handle2_; |
TestCompletionCallback callback_; |
TestCompletionCallback callback2_; |
}; |
+ |
+TEST_F(ClientSocketPoolBaseTest, AdditionalErrorSocketsDontUseSlot) { |
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
+ |
+ EXPECT_EQ(OK, StartRequest("b", kDefaultPriority)); |
+ EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); |
+ EXPECT_EQ(OK, StartRequest("b", kDefaultPriority)); |
+ |
+ EXPECT_EQ(static_cast<int>(requests_.size()), |
+ client_socket_factory_.allocation_count()); |
+ |
+ connect_job_factory_->set_job_type( |
+ TestConnectJob::kMockPendingAdditionalErrorStateJob); |
+ TestReleasingSocketRequest req(pool_.get(), OK, false); |
+ EXPECT_EQ(ERR_IO_PENDING, req.handle()->Init("a", params_, kDefaultPriority, |
+ &req, pool_, BoundNetLog())); |
+ // The next job should complete synchronously |
+ connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
+ |
+ EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); |
+ EXPECT_FALSE(req.handle()->is_initialized()); |
+ EXPECT_FALSE(req.handle()->socket()); |
+ EXPECT_TRUE(req.handle()->is_ssl_error()); |
+ EXPECT_FALSE(req.handle()->tunnel_auth_response_info().headers.get() == NULL); |
+} |
+ |
// http://crbug.com/44724 regression test. |
// We start releasing the pool when we flush on network change. When that |
// happens, the only active references are in the ClientSocketHandles. When a |