OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "net/http/http_pipelined_host_pool.h" | |
6 | |
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" | |
16 | |
17 using testing::_; | |
18 using testing::Ref; | |
19 using testing::Return; | |
20 using testing::ReturnNull; | |
21 | |
22 namespace net { | |
23 | |
24 namespace { | |
25 | |
26 ClientSocketHandle* kDummyConnection = | |
27 reinterpret_cast<ClientSocketHandle*>(188); | |
28 HttpPipelinedStream* kDummyStream = | |
29 reinterpret_cast<HttpPipelinedStream*>(99); | |
30 | |
31 class MockPoolDelegate : public HttpPipelinedHostPool::Delegate { | |
32 public: | |
33 MOCK_METHOD1(OnHttpPipelinedHostHasAdditionalCapacity, | |
34 void(HttpPipelinedHost* host)); | |
35 }; | |
36 | |
37 class MockHostFactory : public HttpPipelinedHost::Factory { | |
38 public: | |
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)); | |
45 }; | |
46 | |
47 class MockHost : public HttpPipelinedHost { | |
48 public: | |
49 MockHost(const Key& key) | |
50 : key_(key) { | |
51 } | |
52 | |
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*()); | |
63 | |
64 virtual const Key& GetKey() const OVERRIDE { return key_; } | |
65 | |
66 private: | |
67 Key key_; | |
68 }; | |
69 | |
70 class HttpPipelinedHostPoolTest : public testing::Test { | |
71 public: | |
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( | |
78 &delegate_, factory_, | |
79 http_server_properties_->GetWeakPtr(), false)), | |
80 was_npn_negotiated_(false), | |
81 protocol_negotiated_(kProtoUnknown) { | |
82 } | |
83 | |
84 void CreateDummyStream(const HttpPipelinedHost::Key& key, | |
85 ClientSocketHandle* connection, | |
86 HttpPipelinedStream* stream, | |
87 MockHost* host) { | |
88 EXPECT_CALL(*host, CreateStreamOnNewPipeline(connection, | |
89 Ref(ssl_config_), | |
90 Ref(proxy_info_), | |
91 Ref(net_log_), | |
92 was_npn_negotiated_, | |
93 protocol_negotiated_)) | |
94 .Times(1) | |
95 .WillOnce(Return(stream)); | |
96 EXPECT_EQ(stream, | |
97 pool_->CreateStreamOnNewPipeline(key, connection, | |
98 ssl_config_, proxy_info_, | |
99 net_log_, was_npn_negotiated_, | |
100 protocol_negotiated_)); | |
101 } | |
102 | |
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)) | |
107 .Times(1) | |
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); | |
114 return mock_host; | |
115 } | |
116 | |
117 HttpPipelinedHost::Key key_; | |
118 MockPoolDelegate delegate_; | |
119 MockHostFactory* factory_; | |
120 MockHost* host_; | |
121 scoped_ptr<HttpServerPropertiesImpl> http_server_properties_; | |
122 scoped_ptr<HttpPipelinedHostPool> pool_; | |
123 | |
124 const SSLConfig ssl_config_; | |
125 const ProxyInfo proxy_info_; | |
126 const BoundNetLog net_log_; | |
127 bool was_npn_negotiated_; | |
128 NextProto protocol_negotiated_; | |
129 }; | |
130 | |
131 TEST_F(HttpPipelinedHostPoolTest, DefaultUnknown) { | |
132 EXPECT_TRUE(pool_->IsKeyEligibleForPipelining(key_)); | |
133 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
134 PIPELINE_UNKNOWN, false)) | |
135 .Times(1) | |
136 .WillOnce(Return(host_)); | |
137 | |
138 CreateDummyStream(key_, kDummyConnection, kDummyStream, host_); | |
139 pool_->OnHostIdle(host_); | |
140 } | |
141 | |
142 TEST_F(HttpPipelinedHostPoolTest, RemembersIncapable) { | |
143 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
144 PIPELINE_UNKNOWN, false)) | |
145 .Times(1) | |
146 .WillOnce(Return(host_)); | |
147 | |
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)) | |
154 .Times(0); | |
155 EXPECT_EQ(NULL, | |
156 pool_->CreateStreamOnNewPipeline(key_, kDummyConnection, | |
157 ssl_config_, proxy_info_, net_log_, | |
158 was_npn_negotiated_, | |
159 protocol_negotiated_)); | |
160 } | |
161 | |
162 TEST_F(HttpPipelinedHostPoolTest, RemembersCapable) { | |
163 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
164 PIPELINE_UNKNOWN, false)) | |
165 .Times(1) | |
166 .WillOnce(Return(host_)); | |
167 | |
168 CreateDummyStream(key_, kDummyConnection, kDummyStream, host_); | |
169 pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE); | |
170 pool_->OnHostIdle(host_); | |
171 EXPECT_TRUE(pool_->IsKeyEligibleForPipelining(key_)); | |
172 | |
173 host_ = new MockHost(key_); | |
174 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
175 PIPELINE_CAPABLE, false)) | |
176 .Times(1) | |
177 .WillOnce(Return(host_)); | |
178 CreateDummyStream(key_, kDummyConnection, kDummyStream, host_); | |
179 pool_->OnHostIdle(host_); | |
180 } | |
181 | |
182 TEST_F(HttpPipelinedHostPoolTest, IncapableIsSticky) { | |
183 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
184 PIPELINE_UNKNOWN, false)) | |
185 .Times(1) | |
186 .WillOnce(Return(host_)); | |
187 | |
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_)); | |
194 } | |
195 | |
196 TEST_F(HttpPipelinedHostPoolTest, RemainsUnknownWithoutFeedback) { | |
197 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
198 PIPELINE_UNKNOWN, false)) | |
199 .Times(1) | |
200 .WillOnce(Return(host_)); | |
201 | |
202 CreateDummyStream(key_, kDummyConnection, kDummyStream, host_); | |
203 pool_->OnHostIdle(host_); | |
204 EXPECT_TRUE(pool_->IsKeyEligibleForPipelining(key_)); | |
205 | |
206 host_ = new MockHost(key_); | |
207 EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _, | |
208 PIPELINE_UNKNOWN, false)) | |
209 .Times(1) | |
210 .WillOnce(Return(host_)); | |
211 | |
212 CreateDummyStream(key_, kDummyConnection, kDummyStream, host_); | |
213 pool_->OnHostIdle(host_); | |
214 } | |
215 | |
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_|. | |
225 } | |
226 | |
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); | |
235 | |
236 EXPECT_CALL(*host1, IsExistingPipelineAvailable()) | |
237 .Times(1) | |
238 .WillOnce(Return(true)); | |
239 EXPECT_TRUE(pool_->IsExistingPipelineAvailableForKey(key1)); | |
240 | |
241 EXPECT_CALL(*host2, IsExistingPipelineAvailable()) | |
242 .Times(1) | |
243 .WillOnce(Return(false)); | |
244 EXPECT_FALSE(pool_->IsExistingPipelineAvailableForKey(key2)); | |
245 | |
246 EXPECT_CALL(*host3, IsExistingPipelineAvailable()) | |
247 .Times(1) | |
248 .WillOnce(Return(true)); | |
249 EXPECT_TRUE(pool_->IsExistingPipelineAvailableForKey(key3)); | |
250 | |
251 EXPECT_FALSE(pool_->IsExistingPipelineAvailableForKey(key4)); | |
252 | |
253 pool_->OnHostIdle(host1); | |
254 pool_->OnHostIdle(host2); | |
255 pool_->OnHostIdle(host3); | |
256 | |
257 delete host_; // Must manually delete, because it's never added to |pool_|. | |
258 } | |
259 | |
260 } // anonymous namespace | |
261 | |
262 } // namespace net | |
OLD | NEW |