Index: net/socket/client_socket_pool_base_unittest.cc |
=================================================================== |
--- net/socket/client_socket_pool_base_unittest.cc (revision 172981) |
+++ net/socket/client_socket_pool_base_unittest.cc (working copy) |
@@ -14,10 +14,12 @@ |
#include "base/memory/scoped_vector.h" |
#include "base/memory/weak_ptr.h" |
#include "base/message_loop.h" |
+#include "base/run_loop.h" |
#include "base/stringprintf.h" |
#include "base/string_number_conversions.h" |
#include "base/threading/platform_thread.h" |
#include "base/values.h" |
+#include "net/base/load_timing_info.h" |
#include "net/base/net_errors.h" |
#include "net/base/net_log.h" |
#include "net/base/net_log_unittest.h" |
@@ -43,6 +45,83 @@ |
const int kDefaultMaxSocketsPerGroup = 2; |
const net::RequestPriority kDefaultPriority = MEDIUM; |
+// Make sure |handle| sets load times are set correctly when it has been |
eroman
2012/12/14 04:08:35
This reads weird, i think there is a "set" too man
mmenke
2012/12/14 13:36:12
Done. I should know by now to vet all my last min
|
+// assigned a reused socket. |
+void TestLoadTimingInfoConnectedReused(const ClientSocketHandle& handle) { |
+ LoadTimingInfo load_timing_info; |
+ // Only pass true in as |is_reused|, as in general, HttpStream types should |
+ // have stricter concepts of reuse than socket pools. |
+ EXPECT_TRUE(handle.GetLoadTimingInfo(true, &load_timing_info)); |
+ |
+ EXPECT_EQ(true, load_timing_info.socket_reused); |
+ EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); |
+ |
+ EXPECT_TRUE(load_timing_info.connect_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.connect_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.dns_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.dns_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.ssl_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.ssl_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.proxy_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.proxy_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.send_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.send_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); |
+} |
+ |
+// Make sure |handle| sets load times are set correctly when it has been |
eroman
2012/12/14 04:08:35
same comment as earlier.
mmenke
2012/12/14 13:36:12
Done.
|
+// assigned a fresh socket. Also runs TestLoadTimingInfoConnectedReused, since |
+// the own of a connection where |is_reused| is false may consider the |
eroman
2012/12/14 04:08:35
typo? "the own of a connection"
mmenke
2012/12/14 13:36:12
Done.
|
+// connection reused. |
+void TestLoadTimingInfoConnectedNotReused(const ClientSocketHandle& handle) { |
+ EXPECT_FALSE(handle.is_reused()); |
+ |
+ LoadTimingInfo load_timing_info; |
+ EXPECT_TRUE(handle.GetLoadTimingInfo(false, &load_timing_info)); |
+ |
+ EXPECT_FALSE(load_timing_info.socket_reused); |
+ EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); |
+ |
+ EXPECT_FALSE(load_timing_info.connect_start.is_null()); |
+ EXPECT_LE(load_timing_info.connect_start, load_timing_info.connect_end); |
+ EXPECT_TRUE(load_timing_info.dns_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.dns_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.ssl_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.ssl_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.proxy_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.proxy_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.send_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.send_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); |
+ |
+ TestLoadTimingInfoConnectedReused(handle); |
+} |
+ |
+// Make sure |handle| sets load times correctly, in the case that it does not |
+// currently have a socket. |
+void TestLoadTimingInfoNotConnected(const ClientSocketHandle& handle) { |
+ // Should only be set to true once a socket is assigned, if at all. |
+ EXPECT_FALSE(handle.is_reused()); |
+ |
+ LoadTimingInfo load_timing_info; |
+ EXPECT_FALSE(handle.GetLoadTimingInfo(false, &load_timing_info)); |
+ |
+ EXPECT_FALSE(load_timing_info.socket_reused); |
+ EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); |
+ |
+ EXPECT_TRUE(load_timing_info.connect_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.connect_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.dns_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.dns_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.ssl_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.ssl_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.proxy_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.proxy_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.send_start.is_null()); |
+ EXPECT_TRUE(load_timing_info.send_end.is_null()); |
+ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); |
+} |
+ |
class TestSocketParams : public base::RefCounted<TestSocketParams> { |
public: |
TestSocketParams() : ignore_limits_(false) {} |
@@ -62,8 +141,12 @@ |
class MockClientSocket : public StreamSocket { |
public: |
- MockClientSocket() : connected_(false), was_used_to_convey_data_(false), |
- num_bytes_read_(0) {} |
+ explicit MockClientSocket(net::NetLog* net_log) |
+ : connected_(false), |
+ net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), |
+ was_used_to_convey_data_(false), |
+ num_bytes_read_(0) { |
+ } |
// Socket implementation. |
virtual int Read( |
@@ -238,7 +321,7 @@ |
AddressList ignored; |
client_socket_factory_->CreateTransportClientSocket( |
ignored, NULL, net::NetLog::Source()); |
- set_socket(new MockClientSocket()); |
+ set_socket(new MockClientSocket(net_log().net_log())); |
switch (job_type_) { |
case kMockJob: |
return DoConnect(true /* successful */, false /* sync */, |
@@ -373,10 +456,13 @@ |
class TestConnectJobFactory |
: public TestClientSocketPoolBase::ConnectJobFactory { |
public: |
- explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) |
+ TestConnectJobFactory(MockClientSocketFactory* client_socket_factory, |
+ NetLog* net_log) |
: job_type_(TestConnectJob::kMockJob), |
job_types_(NULL), |
- client_socket_factory_(client_socket_factory) {} |
+ client_socket_factory_(client_socket_factory), |
+ net_log_(net_log) { |
+} |
virtual ~TestConnectJobFactory() {} |
@@ -409,7 +495,7 @@ |
timeout_duration_, |
delegate, |
client_socket_factory_, |
- NULL); |
+ net_log_); |
} |
virtual base::TimeDelta ConnectionTimeout() const { |
@@ -421,6 +507,7 @@ |
std::list<TestConnectJob::JobType>* job_types_; |
base::TimeDelta timeout_duration_; |
MockClientSocketFactory* const client_socket_factory_; |
+ NetLog* net_log_; |
DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); |
}; |
@@ -638,7 +725,8 @@ |
base::TimeDelta unused_idle_socket_timeout, |
base::TimeDelta used_idle_socket_timeout) { |
DCHECK(!pool_.get()); |
- connect_job_factory_ = new TestConnectJobFactory(&client_socket_factory_); |
+ connect_job_factory_ = new TestConnectJobFactory(&client_socket_factory_, |
+ &net_log_); |
pool_.reset(new TestClientSocketPool(max_sockets, |
max_sockets_per_group, |
&histograms_, |
@@ -671,6 +759,7 @@ |
ScopedVector<TestSocketRequest>* requests() { return test_base_.requests(); } |
size_t completion_count() const { return test_base_.completion_count(); } |
+ CapturingNetLog net_log_; |
bool connect_backup_jobs_enabled_; |
bool cleanup_timer_enabled_; |
MockClientSocketFactory client_socket_factory_; |
@@ -814,6 +903,7 @@ |
TestCompletionCallback callback; |
ClientSocketHandle handle; |
CapturingBoundNetLog log; |
+ TestLoadTimingInfoNotConnected(handle); |
EXPECT_EQ(OK, |
handle.Init("a", |
@@ -824,7 +914,10 @@ |
log.bound())); |
EXPECT_TRUE(handle.is_initialized()); |
EXPECT_TRUE(handle.socket()); |
+ TestLoadTimingInfoConnectedNotReused(handle); |
+ |
handle.Reset(); |
+ TestLoadTimingInfoNotConnected(handle); |
CapturingNetLog::CapturedEntryList entries; |
log.GetEntries(&entries); |
@@ -865,6 +958,7 @@ |
EXPECT_FALSE(handle.socket()); |
EXPECT_FALSE(handle.is_ssl_error()); |
EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL); |
+ TestLoadTimingInfoNotConnected(handle); |
CapturingNetLog::CapturedEntryList entries; |
log.GetEntries(&entries); |
@@ -1634,6 +1728,7 @@ |
EXPECT_EQ(OK, callback.WaitForResult()); |
EXPECT_FALSE(handle.is_reused()); |
+ TestLoadTimingInfoConnectedNotReused(handle); |
EXPECT_EQ(2, client_socket_factory_.allocation_count()); |
} |
@@ -1688,10 +1783,15 @@ |
log.bound()); |
EXPECT_EQ(ERR_IO_PENDING, rv); |
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle)); |
+ TestLoadTimingInfoNotConnected(handle); |
+ |
EXPECT_EQ(OK, callback.WaitForResult()); |
EXPECT_TRUE(handle.is_initialized()); |
EXPECT_TRUE(handle.socket()); |
+ TestLoadTimingInfoConnectedNotReused(handle); |
+ |
handle.Reset(); |
+ TestLoadTimingInfoNotConnected(handle); |
CapturingNetLog::CapturedEntryList entries; |
log.GetEntries(&entries); |
@@ -2044,6 +2144,7 @@ |
// Use and release the socket. |
EXPECT_EQ(1, handle.socket()->Write(NULL, 1, CompletionCallback())); |
+ TestLoadTimingInfoConnectedNotReused(handle); |
handle.Reset(); |
// Should now have one idle socket. |
@@ -2060,6 +2161,7 @@ |
log.bound()); |
ASSERT_EQ(OK, rv); |
EXPECT_TRUE(handle.is_reused()); |
+ TestLoadTimingInfoConnectedReused(handle); |
ASSERT_TRUE(pool_->HasGroup("a")); |
EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
@@ -3383,11 +3485,43 @@ |
ASSERT_EQ(OK, callback1.WaitForResult()); |
+ // Make sure if a preconneced socket is not fully connected when a request |
+ // starts, it has a connect start time. |
+ TestLoadTimingInfoConnectedNotReused(handle1); |
handle1.Reset(); |
EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); |
} |
+// Checks that fully connected preconnect jobs have no connect times, and are |
+// marked as reused. |
+TEST_F(ClientSocketPoolBaseTest, ConnectedPreconnectJobsHaveNoConnectTimes) { |
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
+ connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
+ pool_->RequestSockets("a", ¶ms_, 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")); |
+ |
+ ClientSocketHandle handle; |
+ TestCompletionCallback callback; |
+ EXPECT_EQ(OK, handle.Init("a", |
+ params_, |
+ kDefaultPriority, |
+ callback.callback(), |
+ pool_.get(), |
+ BoundNetLog())); |
+ |
+ // Make sure thee idle socket was used. |
eroman
2012/12/14 04:08:35
thee --> the; unless thou wants to sound pompous.
mmenke
2012/12/14 13:36:12
Done.
|
+ EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
+ |
+ TestLoadTimingInfoConnectedReused(handle); |
+ handle.Reset(); |
+ TestLoadTimingInfoNotConnected(handle); |
+} |
+ |
// http://crbug.com/64940 regression test. |
TEST_F(ClientSocketPoolBaseTest, PreconnectClosesIdleSocketRemovesGroup) { |
const int kMaxTotalSockets = 3; |