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_impl.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "net/http/http_pipelined_connection.h" 9 #include "net/http/http_pipelined_host_test_util.h" 10 #include "net/proxy/proxy_info.h" 11 #include "net/ssl/ssl_config_service.h" 12 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 using testing::_; 16 using testing::NiceMock; 17 using testing::Ref; 18 using testing::Return; 19 using testing::ReturnNull; 20 21 namespace net { 22 23 namespace { 24 25 ClientSocketHandle* kDummyConnection = 26 reinterpret_cast<ClientSocketHandle*>(84); 27 HttpPipelinedStream* kDummyStream = 28 reinterpret_cast<HttpPipelinedStream*>(42); 29 30 class HttpPipelinedHostImplTest : public testing::Test { 31 public: 32 HttpPipelinedHostImplTest() 33 : key_(HostPortPair("host", 123)), 34 factory_(new MockPipelineFactory), // Owned by host_. 35 host_(new HttpPipelinedHostImpl(&delegate_, key_, factory_, 36 PIPELINE_CAPABLE)) { 37 } 38 39 void SetCapability(HttpPipelinedHostCapability capability) { 40 factory_ = new MockPipelineFactory; 41 host_.reset(new HttpPipelinedHostImpl( 42 &delegate_, key_, factory_, capability)); 43 } 44 45 MockPipeline* AddTestPipeline(int depth, bool usable, bool active) { 46 MockPipeline* pipeline = new MockPipeline(depth, usable, active); 47 EXPECT_CALL(*factory_, CreateNewPipeline(kDummyConnection, host_.get(), 48 MatchesOrigin(key_.origin()), 49 Ref(ssl_config_), Ref(proxy_info_), 50 Ref(net_log_), true, 51 kProtoSPDY2)) 52 .Times(1) 53 .WillOnce(Return(pipeline)); 54 EXPECT_CALL(*pipeline, CreateNewStream()) 55 .Times(1) 56 .WillOnce(Return(kDummyStream)); 57 EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline( 58 kDummyConnection, ssl_config_, proxy_info_, net_log_, true, 59 kProtoSPDY2)); 60 return pipeline; 61 } 62 63 void ClearTestPipeline(MockPipeline* pipeline) { 64 pipeline->SetState(0, true, true); 65 host_->OnPipelineHasCapacity(pipeline); 66 } 67 68 NiceMock<MockHostDelegate> delegate_; 69 HttpPipelinedHost::Key key_; 70 MockPipelineFactory* factory_; 71 scoped_ptr<HttpPipelinedHostImpl> host_; 72 73 SSLConfig ssl_config_; 74 ProxyInfo proxy_info_; 75 BoundNetLog net_log_; 76 }; 77 78 TEST_F(HttpPipelinedHostImplTest, Delegate) { 79 EXPECT_TRUE(key_.origin().Equals(host_->GetKey().origin())); 80 } 81 82 TEST_F(HttpPipelinedHostImplTest, OnUnusablePipelineHasCapacity) { 83 MockPipeline* pipeline = AddTestPipeline(0, false, true); 84 85 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 86 .Times(0); 87 EXPECT_CALL(delegate_, OnHostIdle(host_.get())) 88 .Times(1); 89 host_->OnPipelineHasCapacity(pipeline); 90 } 91 92 TEST_F(HttpPipelinedHostImplTest, OnUsablePipelineHasCapacity) { 93 MockPipeline* pipeline = AddTestPipeline(1, true, true); 94 95 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 96 .Times(1); 97 EXPECT_CALL(delegate_, OnHostIdle(host_.get())) 98 .Times(0); 99 100 host_->OnPipelineHasCapacity(pipeline); 101 102 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 103 .Times(1); 104 EXPECT_CALL(delegate_, OnHostIdle(host_.get())) 105 .Times(1); 106 ClearTestPipeline(pipeline); 107 } 108 109 TEST_F(HttpPipelinedHostImplTest, IgnoresUnusablePipeline) { 110 MockPipeline* pipeline = AddTestPipeline(1, false, true); 111 112 EXPECT_FALSE(host_->IsExistingPipelineAvailable()); 113 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 114 115 ClearTestPipeline(pipeline); 116 } 117 118 TEST_F(HttpPipelinedHostImplTest, IgnoresInactivePipeline) { 119 MockPipeline* pipeline = AddTestPipeline(1, true, false); 120 121 EXPECT_FALSE(host_->IsExistingPipelineAvailable()); 122 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 123 124 ClearTestPipeline(pipeline); 125 } 126 127 TEST_F(HttpPipelinedHostImplTest, IgnoresFullPipeline) { 128 MockPipeline* pipeline = AddTestPipeline( 129 HttpPipelinedHostImpl::max_pipeline_depth(), true, true); 130 131 EXPECT_FALSE(host_->IsExistingPipelineAvailable()); 132 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 133 134 ClearTestPipeline(pipeline); 135 } 136 137 TEST_F(HttpPipelinedHostImplTest, PicksLeastLoadedPipeline) { 138 MockPipeline* full_pipeline = AddTestPipeline( 139 HttpPipelinedHostImpl::max_pipeline_depth(), true, true); 140 MockPipeline* usable_pipeline = AddTestPipeline( 141 HttpPipelinedHostImpl::max_pipeline_depth() - 1, true, true); 142 MockPipeline* empty_pipeline = AddTestPipeline(0, true, true); 143 144 EXPECT_TRUE(host_->IsExistingPipelineAvailable()); 145 EXPECT_CALL(*empty_pipeline, CreateNewStream()) 146 .Times(1) 147 .WillOnce(ReturnNull()); 148 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 149 150 ClearTestPipeline(full_pipeline); 151 ClearTestPipeline(usable_pipeline); 152 ClearTestPipeline(empty_pipeline); 153 } 154 155 TEST_F(HttpPipelinedHostImplTest, OpensUpOnPipelineSuccess) { 156 SetCapability(PIPELINE_UNKNOWN); 157 MockPipeline* pipeline = AddTestPipeline(1, true, true); 158 159 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 160 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 161 .Times(1); 162 host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK); 163 164 EXPECT_CALL(*pipeline, CreateNewStream()) 165 .Times(1) 166 .WillOnce(Return(kDummyStream)); 167 EXPECT_EQ(kDummyStream, host_->CreateStreamOnExistingPipeline()); 168 169 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 170 .Times(1); 171 ClearTestPipeline(pipeline); 172 } 173 174 TEST_F(HttpPipelinedHostImplTest, OpensAllPipelinesOnPipelineSuccess) { 175 SetCapability(PIPELINE_UNKNOWN); 176 MockPipeline* pipeline1 = AddTestPipeline(1, false, true); 177 MockPipeline* pipeline2 = AddTestPipeline(1, true, true); 178 179 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 180 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 181 .Times(1); 182 host_->OnPipelineFeedback(pipeline1, HttpPipelinedConnection::OK); 183 184 EXPECT_CALL(*pipeline2, CreateNewStream()) 185 .Times(1) 186 .WillOnce(Return(kDummyStream)); 187 EXPECT_EQ(kDummyStream, host_->CreateStreamOnExistingPipeline()); 188 189 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 190 .Times(2); 191 ClearTestPipeline(pipeline1); 192 ClearTestPipeline(pipeline2); 193 } 194 195 TEST_F(HttpPipelinedHostImplTest, ShutsDownOnOldVersion) { 196 SetCapability(PIPELINE_UNKNOWN); 197 MockPipeline* pipeline = AddTestPipeline(1, true, true); 198 199 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 200 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 201 .Times(0); 202 EXPECT_CALL(delegate_, 203 OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE)) 204 .Times(1); 205 host_->OnPipelineFeedback(pipeline, 206 HttpPipelinedConnection::OLD_HTTP_VERSION); 207 208 ClearTestPipeline(pipeline); 209 EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline( 210 kDummyConnection, ssl_config_, proxy_info_, net_log_, true, 211 kProtoSPDY2)); 212 } 213 214 TEST_F(HttpPipelinedHostImplTest, ShutsDownOnAuthenticationRequired) { 215 SetCapability(PIPELINE_UNKNOWN); 216 MockPipeline* pipeline = AddTestPipeline(1, true, true); 217 218 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 219 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 220 .Times(0); 221 EXPECT_CALL(delegate_, 222 OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE)) 223 .Times(1); 224 host_->OnPipelineFeedback(pipeline, 225 HttpPipelinedConnection::AUTHENTICATION_REQUIRED); 226 227 ClearTestPipeline(pipeline); 228 EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline( 229 kDummyConnection, ssl_config_, proxy_info_, net_log_, true, 230 kProtoSPDY2)); 231 } 232 233 TEST_F(HttpPipelinedHostImplTest, ConnectionCloseHasNoEffect) { 234 SetCapability(PIPELINE_UNKNOWN); 235 MockPipeline* pipeline = AddTestPipeline(1, true, true); 236 237 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 238 .Times(0); 239 EXPECT_CALL(delegate_, OnHostDeterminedCapability(host_.get(), _)) 240 .Times(0); 241 host_->OnPipelineFeedback(pipeline, 242 HttpPipelinedConnection::MUST_CLOSE_CONNECTION); 243 EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline()); 244 245 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 246 .Times(1); 247 ClearTestPipeline(pipeline); 248 } 249 250 TEST_F(HttpPipelinedHostImplTest, SuccessesLeadToCapable) { 251 SetCapability(PIPELINE_UNKNOWN); 252 MockPipeline* pipeline = AddTestPipeline(1, true, true); 253 254 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 255 .Times(1); 256 EXPECT_CALL(delegate_, 257 OnHostDeterminedCapability(host_.get(), PIPELINE_CAPABLE)) 258 .Times(1); 259 host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK); 260 261 pipeline->SetState(3, true, true); 262 host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK); 263 host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK); 264 265 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 266 .Times(1); 267 ClearTestPipeline(pipeline); 268 } 269 270 TEST_F(HttpPipelinedHostImplTest, IgnoresSocketErrorOnFirstRequest) { 271 SetCapability(PIPELINE_UNKNOWN); 272 MockPipeline* pipeline = AddTestPipeline(1, true, true); 273 274 EXPECT_CALL(delegate_, OnHostDeterminedCapability(host_.get(), _)) 275 .Times(0); 276 host_->OnPipelineFeedback(pipeline, 277 HttpPipelinedConnection::PIPELINE_SOCKET_ERROR); 278 279 EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get())) 280 .Times(1); 281 host_->OnPipelineFeedback(pipeline, 282 HttpPipelinedConnection::OK); 283 284 EXPECT_CALL(delegate_, 285 OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE)) 286 .Times(1); 287 host_->OnPipelineFeedback(pipeline, 288 HttpPipelinedConnection::PIPELINE_SOCKET_ERROR); 289 290 ClearTestPipeline(pipeline); 291 } 292 293 TEST_F(HttpPipelinedHostImplTest, HeedsSocketErrorOnFirstRequestWithPipeline) { 294 SetCapability(PIPELINE_UNKNOWN); 295 MockPipeline* pipeline = AddTestPipeline(2, true, true); 296 297 EXPECT_CALL(delegate_, 298 OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE)) 299 .Times(1); 300 host_->OnPipelineFeedback(pipeline, 301 HttpPipelinedConnection::PIPELINE_SOCKET_ERROR); 302 303 ClearTestPipeline(pipeline); 304 } 305 306 } // anonymous namespace 307 308 } // namespace net 309