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/base/ssl_config_service.h"
10 #include "net/http/http_pipelined_host.h"
11 #include "net/http/http_pipelined_host_capability.h"
12 #include "net/http/http_server_properties_impl.h"
13 #include "net/proxy/proxy_info.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(&delegate_
, factory_
,
78 http_server_properties_
.get(), false)),
79 was_npn_negotiated_(false),
80 protocol_negotiated_(kProtoUnknown
) {
83 void CreateDummyStream(const HttpPipelinedHost::Key
& key
,
84 ClientSocketHandle
* connection
,
85 HttpPipelinedStream
* stream
,
87 EXPECT_CALL(*host
, CreateStreamOnNewPipeline(connection
,
92 protocol_negotiated_
))
94 .WillOnce(Return(stream
));
96 pool_
->CreateStreamOnNewPipeline(key
, connection
,
97 ssl_config_
, proxy_info_
,
98 net_log_
, was_npn_negotiated_
,
99 protocol_negotiated_
));
102 MockHost
* CreateDummyHost(const HttpPipelinedHost::Key
& key
) {
103 MockHost
* mock_host
= new MockHost(key
);
104 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key
), _
,
105 PIPELINE_UNKNOWN
, false))
107 .WillOnce(Return(mock_host
));
108 ClientSocketHandle
* dummy_connection
=
109 reinterpret_cast<ClientSocketHandle
*>(base::RandUint64());
110 HttpPipelinedStream
* dummy_stream
=
111 reinterpret_cast<HttpPipelinedStream
*>(base::RandUint64());
112 CreateDummyStream(key
, dummy_connection
, dummy_stream
, mock_host
);
116 HttpPipelinedHost::Key key_
;
117 MockPoolDelegate delegate_
;
118 MockHostFactory
* factory_
;
120 scoped_ptr
<HttpServerPropertiesImpl
> http_server_properties_
;
121 scoped_ptr
<HttpPipelinedHostPool
> pool_
;
123 const SSLConfig ssl_config_
;
124 const ProxyInfo proxy_info_
;
125 const BoundNetLog net_log_
;
126 bool was_npn_negotiated_
;
127 NextProto protocol_negotiated_
;
130 TEST_F(HttpPipelinedHostPoolTest
, DefaultUnknown
) {
131 EXPECT_TRUE(pool_
->IsKeyEligibleForPipelining(key_
));
132 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
133 PIPELINE_UNKNOWN
, false))
135 .WillOnce(Return(host_
));
137 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
138 pool_
->OnHostIdle(host_
);
141 TEST_F(HttpPipelinedHostPoolTest
, RemembersIncapable
) {
142 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
143 PIPELINE_UNKNOWN
, false))
145 .WillOnce(Return(host_
));
147 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
148 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_INCAPABLE
);
149 pool_
->OnHostIdle(host_
);
150 EXPECT_FALSE(pool_
->IsKeyEligibleForPipelining(key_
));
151 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
152 PIPELINE_INCAPABLE
, false))
155 pool_
->CreateStreamOnNewPipeline(key_
, kDummyConnection
,
156 ssl_config_
, proxy_info_
, net_log_
,
158 protocol_negotiated_
));
161 TEST_F(HttpPipelinedHostPoolTest
, RemembersCapable
) {
162 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
163 PIPELINE_UNKNOWN
, false))
165 .WillOnce(Return(host_
));
167 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
168 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
169 pool_
->OnHostIdle(host_
);
170 EXPECT_TRUE(pool_
->IsKeyEligibleForPipelining(key_
));
172 host_
= new MockHost(key_
);
173 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
174 PIPELINE_CAPABLE
, false))
176 .WillOnce(Return(host_
));
177 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
178 pool_
->OnHostIdle(host_
);
181 TEST_F(HttpPipelinedHostPoolTest
, IncapableIsSticky
) {
182 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
183 PIPELINE_UNKNOWN
, false))
185 .WillOnce(Return(host_
));
187 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
188 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
189 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_INCAPABLE
);
190 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
191 pool_
->OnHostIdle(host_
);
192 EXPECT_FALSE(pool_
->IsKeyEligibleForPipelining(key_
));
195 TEST_F(HttpPipelinedHostPoolTest
, RemainsUnknownWithoutFeedback
) {
196 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
197 PIPELINE_UNKNOWN
, false))
199 .WillOnce(Return(host_
));
201 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
202 pool_
->OnHostIdle(host_
);
203 EXPECT_TRUE(pool_
->IsKeyEligibleForPipelining(key_
));
205 host_
= new MockHost(key_
);
206 EXPECT_CALL(*factory_
, CreateNewHost(pool_
.get(), Ref(key_
), _
,
207 PIPELINE_UNKNOWN
, false))
209 .WillOnce(Return(host_
));
211 CreateDummyStream(key_
, kDummyConnection
, kDummyStream
, host_
);
212 pool_
->OnHostIdle(host_
);
215 TEST_F(HttpPipelinedHostPoolTest
, PopulatesServerProperties
) {
216 EXPECT_EQ(PIPELINE_UNKNOWN
,
217 http_server_properties_
->GetPipelineCapability(
218 host_
->GetKey().origin()));
219 pool_
->OnHostDeterminedCapability(host_
, PIPELINE_CAPABLE
);
220 EXPECT_EQ(PIPELINE_CAPABLE
,
221 http_server_properties_
->GetPipelineCapability(
222 host_
->GetKey().origin()));
223 delete host_
; // Must manually delete, because it's never added to |pool_|.
226 TEST_F(HttpPipelinedHostPoolTest
, MultipleKeys
) {
227 HttpPipelinedHost::Key
key1(HostPortPair("host", 123));
228 HttpPipelinedHost::Key
key2(HostPortPair("host", 456));
229 HttpPipelinedHost::Key
key3(HostPortPair("other", 456));
230 HttpPipelinedHost::Key
key4(HostPortPair("other", 789));
231 MockHost
* host1
= CreateDummyHost(key1
);
232 MockHost
* host2
= CreateDummyHost(key2
);
233 MockHost
* host3
= CreateDummyHost(key3
);
235 EXPECT_CALL(*host1
, IsExistingPipelineAvailable())
237 .WillOnce(Return(true));
238 EXPECT_TRUE(pool_
->IsExistingPipelineAvailableForKey(key1
));
240 EXPECT_CALL(*host2
, IsExistingPipelineAvailable())
242 .WillOnce(Return(false));
243 EXPECT_FALSE(pool_
->IsExistingPipelineAvailableForKey(key2
));
245 EXPECT_CALL(*host3
, IsExistingPipelineAvailable())
247 .WillOnce(Return(true));
248 EXPECT_TRUE(pool_
->IsExistingPipelineAvailableForKey(key3
));
250 EXPECT_FALSE(pool_
->IsExistingPipelineAvailableForKey(key4
));
252 pool_
->OnHostIdle(host1
);
253 pool_
->OnHostIdle(host2
);
254 pool_
->OnHostIdle(host3
);
256 delete host_
; // Must manually delete, because it's never added to |pool_|.
259 } // anonymous namespace