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
3 // found in the LICENSE file.
5 #include "net/http/http_pipelined_host_pool.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/rand_util.h"
9 #include "net/http/http_pipelined_host.h"
10 #include "net/http/http_pipelined_host_capability.h"
11 #include "net/http/http_server_properties_impl.h"
12 #include "net/proxy/proxy_info.h"
13 #include "net/ssl/ssl_config_service.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 using testing::Return
;
20 using testing::ReturnNull
;
26 ClientSocketHandle
* kDummyConnection
=
27 reinterpret_cast<ClientSocketHandle
*>(188);
28 HttpPipelinedStream
* kDummyStream
=
29 reinterpret_cast<HttpPipelinedStream
*>(99);
31 class MockPoolDelegate
: public HttpPipelinedHostPool::Delegate
{
33 MOCK_METHOD1(OnHttpPipelinedHostHasAdditionalCapacity
,
34 void(HttpPipelinedHost
* host
));
37 class MockHostFactory
: public HttpPipelinedHost::Factory
{
39 MOCK_METHOD5(CreateNewHost
, HttpPipelinedHost
*(
40 HttpPipelinedHost::Delegate
* delegate
,
41 const HttpPipelinedHost::Key
& key
,
42 HttpPipelinedConnection::Factory
* factory
,
43 HttpPipelinedHostCapability capability
,
44 bool force_pipelining
));
47 class MockHost
: public HttpPipelinedHost
{
49 MockHost(const Key
& key
)
53 MOCK_METHOD6(CreateStreamOnNewPipeline
, HttpPipelinedStream
*(
54 ClientSocketHandle
* connection
,
55 const SSLConfig
& used_ssl_config
,
56 const ProxyInfo
& used_proxy_info
,
57 const BoundNetLog
& net_log
,
58 bool was_npn_negotiated
,
59 NextProto protocol_negotiated
));
60 MOCK_METHOD0(CreateStreamOnExistingPipeline
, HttpPipelinedStream
*());
61 MOCK_CONST_METHOD0(IsExistingPipelineAvailable
, bool());
62 MOCK_CONST_METHOD0(PipelineInfoToValue
, base::Value
*());
64 virtual const Key
& GetKey() const OVERRIDE
{ return key_
; }
70 class HttpPipelinedHostPoolTest
: public testing::Test
{
72 HttpPipelinedHostPoolTest()
73 : key_(HostPortPair("host", 123)),
74 factory_(new MockHostFactory
), // Owned by pool_.
75 host_(new MockHost(key_
)), // Owned by pool_.
76 http_server_properties_(new HttpServerPropertiesImpl()),
77 pool_(new HttpPipelinedHostPool(
79 http_server_properties_
->GetWeakPtr(), false)),
80 was_npn_negotiated_(false),
81 protocol_negotiated_(kProtoUnknown
) {
84 void CreateDummyStream(const HttpPipelinedHost::Key
& key
,
85 ClientSocketHandle
* connection
,
86 HttpPipelinedStream
* stream
,
88 EXPECT_CALL(*host
, CreateStreamOnNewPipeline(connection
,
93 protocol_negotiated_
))
95 .WillOnce(Return(stream
));
97 pool_
->CreateStreamOnNewPipeline(key
, connection
,
98 ssl_config_
, proxy_info_
,
99 net_log_
, was_npn_negotiated_
,
100 protocol_negotiated_
));
103 MockHost
* CreateDummyHost(const HttpPipelinedHost::Key
& key
) {
104 MockHost
* mock_host
= new MockHost(key
);
105 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key
), _
,
106 PIPELINE_UNKNOWN
, false))
108 .WillOnce(Return(mock_host
));
109 ClientSocketHandle
* dummy_connection
=
110 reinterpret_cast<ClientSocketHandle
*>(base::RandUint64());
111 HttpPipelinedStream
* dummy_stream
=
112 reinterpret_cast<HttpPipelinedStream
*>(base::RandUint64());
113 CreateDummyStream(key
, dummy_connection
, dummy_stream
, mock_host
);
117 HttpPipelinedHost::Key key_
;
118 MockPoolDelegate delegate_
;
119 MockHostFactory
* factory_
;
121 scoped_ptr
<HttpServerPropertiesImpl
> http_server_properties_
;
122 scoped_ptr
<HttpPipelinedHostPool
> pool_
;
124 const SSLConfig ssl_config_
;
125 const ProxyInfo proxy_info_
;
126 const BoundNetLog net_log_
;
127 bool was_npn_negotiated_
;
128 NextProto protocol_negotiated_
;
131 TEST_F(HttpPipelinedHostPoolTest
, DefaultUnknown
) {
132 EXPECT_TRUE(pool_
->IsKeyEligibleForPipelining(key_
));
133 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
134 PIPELINE_UNKNOWN
, false))
136 .WillOnce(Return(host_
));
138 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
139 pool_
->OnHostIdle(host_
);
142 TEST_F(HttpPipelinedHostPoolTest
, RemembersIncapable
) {
143 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
144 PIPELINE_UNKNOWN
, false))
146 .WillOnce(Return(host_
));
148 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
149 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_INCAPABLE
);
150 pool_
->OnHostIdle(host_
);
151 EXPECT_FALSE(pool_
->IsKeyEligibleForPipelining(key_
));
152 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
153 PIPELINE_INCAPABLE
, false))
156 pool_
->CreateStreamOnNewPipeline(key_
, kDummyConnection
,
157 ssl_config_
, proxy_info_
, net_log_
,
159 protocol_negotiated_
));
162 TEST_F(HttpPipelinedHostPoolTest
, RemembersCapable
) {
163 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
164 PIPELINE_UNKNOWN
, false))
166 .WillOnce(Return(host_
));
168 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
169 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
170 pool_
->OnHostIdle(host_
);
171 EXPECT_TRUE(pool_
->IsKeyEligibleForPipelining(key_
));
173 host_
= new MockHost(key_
);
174 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
175 PIPELINE_CAPABLE
, false))
177 .WillOnce(Return(host_
));
178 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
179 pool_
->OnHostIdle(host_
);
182 TEST_F(HttpPipelinedHostPoolTest
, IncapableIsSticky
) {
183 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
184 PIPELINE_UNKNOWN
, false))
186 .WillOnce(Return(host_
));
188 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
189 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
190 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_INCAPABLE
);
191 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
192 pool_
->OnHostIdle(host_
);
193 EXPECT_FALSE(pool_
->IsKeyEligibleForPipelining(key_
));
196 TEST_F(HttpPipelinedHostPoolTest
, RemainsUnknownWithoutFeedback
) {
197 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
198 PIPELINE_UNKNOWN
, false))
200 .WillOnce(Return(host_
));
202 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
203 pool_
->OnHostIdle(host_
);
204 EXPECT_TRUE(pool_
->IsKeyEligibleForPipelining(key_
));
206 host_
= new MockHost(key_
);
207 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
208 PIPELINE_UNKNOWN
, false))
210 .WillOnce(Return(host_
));
212 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
213 pool_
->OnHostIdle(host_
);
216 TEST_F(HttpPipelinedHostPoolTest
, PopulatesServerProperties
) {
217 EXPECT_EQ(PIPELINE_UNKNOWN
,
218 http_server_properties_
->GetPipelineCapability(
219 host_
->GetKey().origin()));
220 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
221 EXPECT_EQ(PIPELINE_CAPABLE
,
222 http_server_properties_
->GetPipelineCapability(
223 host_
->GetKey().origin()));
224 delete host_
; // Must manually delete, because it's never added to |pool_|.
227 TEST_F(HttpPipelinedHostPoolTest
, MultipleKeys
) {
228 HttpPipelinedHost::Key
key1(HostPortPair("host", 123));
229 HttpPipelinedHost::Key
key2(HostPortPair("host", 456));
230 HttpPipelinedHost::Key
key3(HostPortPair("other", 456));
231 HttpPipelinedHost::Key
key4(HostPortPair("other", 789));
232 MockHost
* host1
= CreateDummyHost(key1
);
233 MockHost
* host2
= CreateDummyHost(key2
);
234 MockHost
* host3
= CreateDummyHost(key3
);
236 EXPECT_CALL(*host1
, IsExistingPipelineAvailable())
238 .WillOnce(Return(true));
239 EXPECT_TRUE(pool_
->IsExistingPipelineAvailableForKey(key1
));
241 EXPECT_CALL(*host2
, IsExistingPipelineAvailable())
243 .WillOnce(Return(false));
244 EXPECT_FALSE(pool_
->IsExistingPipelineAvailableForKey(key2
));
246 EXPECT_CALL(*host3
, IsExistingPipelineAvailable())
248 .WillOnce(Return(true));
249 EXPECT_TRUE(pool_
->IsExistingPipelineAvailableForKey(key3
));
251 EXPECT_FALSE(pool_
->IsExistingPipelineAvailableForKey(key4
));
253 pool_
->OnHostIdle(host1
);
254 pool_
->OnHostIdle(host2
);
255 pool_
->OnHostIdle(host3
);
257 delete host_
; // Must manually delete, because it's never added to |pool_|.
260 } // anonymous namespace