summaryrefslogtreecommitdiffstats
path: root/net/socket/client_socket_pool_base_unittest.cc
diff options
context:
space:
mode:
authordavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-26 20:12:28 +0000
committerdavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-26 20:12:28 +0000
commit0dc88b379e74db1f8240062e8f9fc64a5753b3cd (patch)
treea0804fb95a36489da03b685a07ab7fec8e471dab /net/socket/client_socket_pool_base_unittest.cc
parent5f95e5312410f2f26254ec17d2adbe2c75395152 (diff)
downloadchromium_src-0dc88b379e74db1f8240062e8f9fc64a5753b3cd.zip
chromium_src-0dc88b379e74db1f8240062e8f9fc64a5753b3cd.tar.gz
chromium_src-0dc88b379e74db1f8240062e8f9fc64a5753b3cd.tar.bz2
Use sockets with unread data if they've never been used before.
This fixes preconnects to SPDY-capable origins. StreamSocket's semantics change slightly. WasEverUsed() for layered sockets is now whether the top-level socket has read or written user data, rather than whether the underlying transport socket was used. Change SSL and SOCKS socket implementations to use the new WasEverUsed() semantics. This doesn't affect SOCKS much except that preconnect misses now time out more aggressively. For SSL, it fixes the SPDY issue. Add tests for SSL socket and socket pool implementations. BUG=334467 Review URL: https://codereview.chromium.org/169643006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259671 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/client_socket_pool_base_unittest.cc')
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc66
1 files changed, 64 insertions, 2 deletions
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 46f4e40..605af72 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -116,14 +116,26 @@ class MockClientSocket : public StreamSocket {
public:
explicit MockClientSocket(net::NetLog* net_log)
: connected_(false),
+ has_unread_data_(false),
net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)),
was_used_to_convey_data_(false) {
}
+ // Sets whether the socket has unread data. If true, the next call to Read()
+ // will return 1 byte and IsConnectedAndIdle() will return false.
+ void set_has_unread_data(bool has_unread_data) {
+ has_unread_data_ = has_unread_data;
+ }
+
// Socket implementation.
virtual int Read(
IOBuffer* /* buf */, int len,
const CompletionCallback& /* callback */) OVERRIDE {
+ if (has_unread_data_ && len > 0) {
+ has_unread_data_ = false;
+ was_used_to_convey_data_ = true;
+ return 1;
+ }
return ERR_UNEXPECTED;
}
@@ -144,7 +156,9 @@ class MockClientSocket : public StreamSocket {
virtual void Disconnect() OVERRIDE { connected_ = false; }
virtual bool IsConnected() const OVERRIDE { return connected_; }
- virtual bool IsConnectedAndIdle() const OVERRIDE { return connected_; }
+ virtual bool IsConnectedAndIdle() const OVERRIDE {
+ return connected_ && !has_unread_data_;
+ }
virtual int GetPeerAddress(IPEndPoint* /* address */) const OVERRIDE {
return ERR_UNEXPECTED;
@@ -176,6 +190,7 @@ class MockClientSocket : public StreamSocket {
private:
bool connected_;
+ bool has_unread_data_;
BoundNetLog net_log_;
bool was_used_to_convey_data_;
@@ -245,6 +260,7 @@ class TestConnectJob : public ConnectJob {
kMockPendingRecoverableJob,
kMockAdditionalErrorStateJob,
kMockPendingAdditionalErrorStateJob,
+ kMockUnreadDataJob,
};
// The kMockPendingJob uses a slight delay before allowing the connect
@@ -372,6 +388,12 @@ class TestConnectJob : public ConnectJob {
false /* recoverable */),
base::TimeDelta::FromMilliseconds(2));
return ERR_IO_PENDING;
+ case kMockUnreadDataJob: {
+ int ret = DoConnect(true /* successful */, false /* sync */,
+ false /* recoverable */);
+ static_cast<MockClientSocket*>(socket())->set_has_unread_data(true);
+ return ret;
+ }
default:
NOTREACHED();
SetSocket(scoped_ptr<StreamSocket>());
@@ -3541,7 +3563,7 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectJobsTakenByNormalRequests) {
ASSERT_EQ(OK, callback1.WaitForResult());
- // Make sure if a preconneced socket is not fully connected when a request
+ // Make sure if a preconnected socket is not fully connected when a request
// starts, it has a connect start time.
TestLoadTimingInfoConnectedNotReused(handle1);
handle1.Reset();
@@ -3720,6 +3742,46 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectWithBackupJob) {
EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a"));
}
+// Tests that a preconnect that starts out with unread data can still be used.
+// http://crbug.com/334467
+TEST_F(ClientSocketPoolBaseTest, PreconnectWithUnreadData) {
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockUnreadDataJob);
+
+ pool_->RequestSockets("a", &params_, 1, BoundNetLog());
+
+ ASSERT_TRUE(pool_->HasGroup("a"));
+ EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
+ EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
+ EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a"));
+
+ // Fail future jobs to be sure that handle receives the preconnected socket
+ // rather than closing it and making a new one.
+ connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ EXPECT_EQ(OK, handle.Init("a",
+ params_,
+ DEFAULT_PRIORITY,
+ callback.callback(),
+ pool_.get(),
+ BoundNetLog()));
+
+ ASSERT_TRUE(pool_->HasGroup("a"));
+ EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
+ EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
+ EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
+
+ // Drain the pending read.
+ EXPECT_EQ(1, handle.socket()->Read(NULL, 1, CompletionCallback()));
+
+ TestLoadTimingInfoConnectedReused(handle);
+ handle.Reset();
+
+ // The socket should be usable now that it's idle again.
+ EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a"));
+}
+
class MockLayeredPool : public HigherLayeredPool {
public:
MockLayeredPool(TestClientSocketPool* pool,