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 <string> 6 7 #include "base/memory/ref_counted.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_vector.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "net/base/address_list.h" 13 #include "net/base/io_buffer.h" 14 #include "net/base/net_errors.h" 15 #include "net/base/net_util.h" 16 #include "net/base/request_priority.h" 17 #include "net/dns/host_cache.h" 18 #include "net/dns/mock_host_resolver.h" 19 #include "net/http/http_auth_handler_mock.h" 20 #include "net/http/http_network_session.h" 21 #include "net/http/http_network_transaction.h" 22 #include "net/http/http_request_info.h" 23 #include "net/http/http_server_properties_impl.h" 24 #include "net/proxy/proxy_config_service.h" 25 #include "net/proxy/proxy_service.h" 26 #include "net/socket/client_socket_handle.h" 27 #include "net/socket/client_socket_pool_histograms.h" 28 #include "net/socket/client_socket_pool_manager.h" 29 #include "net/socket/socket_test_util.h" 30 #include "net/ssl/ssl_config_service_defaults.h" 31 #include "testing/gmock/include/gmock/gmock.h" 32 #include "testing/gtest/include/gtest/gtest.h" 33 34 using testing::StrEq; 35 36 namespace net { 37 38 namespace { 39 40 class SimpleProxyConfigService : public ProxyConfigService { 41 public: 42 virtual void AddObserver(Observer* observer) OVERRIDE { 43 observer_ = observer; 44 } 45 46 virtual void RemoveObserver(Observer* observer) OVERRIDE { 47 if (observer_ == observer) { 48 observer_ = NULL; 49 } 50 } 51 52 virtual ConfigAvailability GetLatestProxyConfig( 53 ProxyConfig* config) OVERRIDE { 54 *config = config_; 55 return CONFIG_VALID; 56 } 57 58 void IncrementConfigId() { 59 config_.set_id(config_.id() + 1); 60 observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID); 61 } 62 63 private: 64 ProxyConfig config_; 65 Observer* observer_; 66 }; 67 68 class HttpPipelinedNetworkTransactionTest : public testing::Test { 69 public: 70 HttpPipelinedNetworkTransactionTest() 71 : histograms_("a"), 72 pool_(1, 1, &histograms_, &factory_) { 73 } 74 75 void Initialize(bool force_http_pipelining) { 76 // Normally, this code could just go in SetUp(). For a few of these tests, 77 // we change the default number of sockets per group. That needs to be done 78 // before we construct the HttpNetworkSession. 79 proxy_config_service_ = new SimpleProxyConfigService(); 80 proxy_service_.reset(new ProxyService(proxy_config_service_, NULL, NULL)); 81 ssl_config_ = new SSLConfigServiceDefaults; 82 auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory()); 83 84 HttpNetworkSession::Params session_params; 85 session_params.client_socket_factory = &factory_; 86 session_params.proxy_service = proxy_service_.get(); 87 session_params.host_resolver = &mock_resolver_; 88 session_params.ssl_config_service = ssl_config_.get(); 89 session_params.http_auth_handler_factory = auth_handler_factory_.get(); 90 session_params.http_server_properties = 91 http_server_properties_.GetWeakPtr(); 92 session_params.force_http_pipelining = force_http_pipelining; 93 session_params.http_pipelining_enabled = true; 94 session_ = new HttpNetworkSession(session_params); 95 } 96 97 void AddExpectedConnection(MockRead* reads, size_t reads_count, 98 MockWrite* writes, size_t writes_count) { 99 DeterministicSocketData* data = new DeterministicSocketData( 100 reads, reads_count, writes, writes_count); 101 data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 102 if (reads_count || writes_count) { 103 data->StopAfter(reads_count + writes_count); 104 } 105 factory_.AddSocketDataProvider(data); 106 data_vector_.push_back(data); 107 } 108 109 enum RequestInfoOptions { 110 REQUEST_DEFAULT, 111 REQUEST_MAIN_RESOURCE, 112 }; 113 114 HttpRequestInfo* GetRequestInfo( 115 const char* filename, RequestInfoOptions options = REQUEST_DEFAULT) { 116 std::string url = base::StringPrintf("http://localhost/%s", filename); 117 HttpRequestInfo* request_info = new HttpRequestInfo; 118 request_info->url = GURL(url); 119 request_info->method = "GET"; 120 if (options == REQUEST_MAIN_RESOURCE) { 121 request_info->load_flags = LOAD_MAIN_FRAME; 122 } 123 request_info_vector_.push_back(request_info); 124 return request_info; 125 } 126 127 void ExpectResponse(const std::string& expected, 128 HttpNetworkTransaction& transaction, 129 IoMode io_mode) { 130 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); 131 if (io_mode == ASYNC) { 132 EXPECT_EQ(ERR_IO_PENDING, transaction.Read(buffer.get(), expected.size(), 133 callback_.callback())); 134 data_vector_[0]->RunFor(1); 135 EXPECT_EQ(static_cast<int>(expected.length()), callback_.WaitForResult()); 136 } else { 137 EXPECT_EQ(static_cast<int>(expected.size()), 138 transaction.Read(buffer.get(), expected.size(), 139 callback_.callback())); 140 } 141 std::string actual(buffer->data(), expected.size()); 142 EXPECT_THAT(actual, StrEq(expected)); 143 EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(), 144 callback_.callback())); 145 } 146 147 void CompleteTwoRequests(int data_index, int stop_at_step) { 148 scoped_ptr<HttpNetworkTransaction> one_transaction( 149 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 150 TestCompletionCallback one_callback; 151 EXPECT_EQ(ERR_IO_PENDING, 152 one_transaction->Start(GetRequestInfo("one.html"), 153 one_callback.callback(), BoundNetLog())); 154 EXPECT_EQ(OK, one_callback.WaitForResult()); 155 156 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 157 TestCompletionCallback two_callback; 158 EXPECT_EQ(ERR_IO_PENDING, 159 two_transaction.Start(GetRequestInfo("two.html"), 160 two_callback.callback(), BoundNetLog())); 161 162 TestCompletionCallback one_read_callback; 163 scoped_refptr<IOBuffer> buffer(new IOBuffer(8)); 164 EXPECT_EQ(ERR_IO_PENDING, 165 one_transaction->Read(buffer.get(), 8, 166 one_read_callback.callback())); 167 168 data_vector_[data_index]->SetStop(stop_at_step); 169 data_vector_[data_index]->Run(); 170 EXPECT_EQ(8, one_read_callback.WaitForResult()); 171 data_vector_[data_index]->SetStop(10); 172 std::string actual(buffer->data(), 8); 173 EXPECT_THAT(actual, StrEq("one.html")); 174 EXPECT_EQ(OK, one_transaction->Read(buffer.get(), 8, 175 one_read_callback.callback())); 176 177 EXPECT_EQ(OK, two_callback.WaitForResult()); 178 ExpectResponse("two.html", two_transaction, SYNCHRONOUS); 179 } 180 181 void CompleteFourRequests(RequestInfoOptions options) { 182 scoped_ptr<HttpNetworkTransaction> one_transaction( 183 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 184 TestCompletionCallback one_callback; 185 EXPECT_EQ(ERR_IO_PENDING, 186 one_transaction->Start(GetRequestInfo("one.html", options), 187 one_callback.callback(), BoundNetLog())); 188 EXPECT_EQ(OK, one_callback.WaitForResult()); 189 190 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 191 TestCompletionCallback two_callback; 192 EXPECT_EQ(ERR_IO_PENDING, 193 two_transaction.Start(GetRequestInfo("two.html", options), 194 two_callback.callback(), BoundNetLog())); 195 196 HttpNetworkTransaction three_transaction(DEFAULT_PRIORITY, session_.get()); 197 TestCompletionCallback three_callback; 198 EXPECT_EQ(ERR_IO_PENDING, 199 three_transaction.Start(GetRequestInfo("three.html", options), 200 three_callback.callback(), 201 BoundNetLog())); 202 203 HttpNetworkTransaction four_transaction(DEFAULT_PRIORITY, session_.get()); 204 TestCompletionCallback four_callback; 205 EXPECT_EQ(ERR_IO_PENDING, 206 four_transaction.Start(GetRequestInfo("four.html", options), 207 four_callback.callback(), BoundNetLog())); 208 209 ExpectResponse("one.html", *one_transaction.get(), SYNCHRONOUS); 210 EXPECT_EQ(OK, two_callback.WaitForResult()); 211 ExpectResponse("two.html", two_transaction, SYNCHRONOUS); 212 EXPECT_EQ(OK, three_callback.WaitForResult()); 213 ExpectResponse("three.html", three_transaction, SYNCHRONOUS); 214 215 one_transaction.reset(); 216 EXPECT_EQ(OK, four_callback.WaitForResult()); 217 ExpectResponse("four.html", four_transaction, SYNCHRONOUS); 218 } 219 220 DeterministicMockClientSocketFactory factory_; 221 ClientSocketPoolHistograms histograms_; 222 MockTransportClientSocketPool pool_; 223 ScopedVector<DeterministicSocketData> data_vector_; 224 TestCompletionCallback callback_; 225 ScopedVector<HttpRequestInfo> request_info_vector_; 226 227 SimpleProxyConfigService* proxy_config_service_; 228 scoped_ptr<ProxyService> proxy_service_; 229 MockHostResolver mock_resolver_; 230 scoped_refptr<SSLConfigService> ssl_config_; 231 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_; 232 HttpServerPropertiesImpl http_server_properties_; 233 scoped_refptr<HttpNetworkSession> session_; 234 }; 235 236 TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) { 237 Initialize(false); 238 239 MockWrite writes[] = { 240 MockWrite(SYNCHRONOUS, 0, "GET /test.html HTTP/1.1\r\n" 241 "Host: localhost\r\n" 242 "Connection: keep-alive\r\n\r\n"), 243 }; 244 MockRead reads[] = { 245 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 246 MockRead(SYNCHRONOUS, 2, "Content-Length: 9\r\n\r\n"), 247 MockRead(SYNCHRONOUS, 3, "test.html"), 248 }; 249 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 250 251 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get()); 252 EXPECT_EQ(ERR_IO_PENDING, 253 transaction.Start(GetRequestInfo("test.html"), callback_.callback(), 254 BoundNetLog())); 255 EXPECT_EQ(OK, callback_.WaitForResult()); 256 ExpectResponse("test.html", transaction, SYNCHRONOUS); 257 } 258 259 TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) { 260 Initialize(false); 261 262 MockWrite writes[] = { 263 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 264 "Host: localhost\r\n" 265 "Connection: keep-alive\r\n\r\n"), 266 MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" 267 "Host: localhost\r\n" 268 "Connection: keep-alive\r\n\r\n"), 269 }; 270 MockRead reads[] = { 271 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 272 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 273 MockRead(ASYNC, 4, "one.html"), 274 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 275 MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), 276 MockRead(SYNCHRONOUS, 7, "two.html"), 277 }; 278 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 279 280 CompleteTwoRequests(0, 5); 281 } 282 283 TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) { 284 int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group( 285 HttpNetworkSession::NORMAL_SOCKET_POOL); 286 ClientSocketPoolManager::set_max_sockets_per_group( 287 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 288 Initialize(false); 289 290 MockWrite writes[] = { 291 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 292 "Host: localhost\r\n" 293 "Connection: keep-alive\r\n\r\n"), 294 MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n" 295 "Host: localhost\r\n" 296 "Connection: keep-alive\r\n\r\n"), 297 MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n" 298 "Host: localhost\r\n" 299 "Connection: keep-alive\r\n\r\n"), 300 MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n" 301 "Host: localhost\r\n" 302 "Connection: keep-alive\r\n\r\n"), 303 }; 304 MockRead reads[] = { 305 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 306 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 307 MockRead(SYNCHRONOUS, 3, "one.html"), 308 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 309 MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), 310 MockRead(SYNCHRONOUS, 8, "two.html"), 311 MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"), 312 MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"), 313 MockRead(SYNCHRONOUS, 11, "three.html"), 314 MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"), 315 MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"), 316 MockRead(SYNCHRONOUS, 15, "four.html"), 317 }; 318 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 319 320 CompleteFourRequests(REQUEST_DEFAULT); 321 322 ClientSocketPoolManager::set_max_sockets_per_group( 323 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets); 324 } 325 326 TEST_F(HttpPipelinedNetworkTransactionTest, WontPipelineMainResource) { 327 int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group( 328 HttpNetworkSession::NORMAL_SOCKET_POOL); 329 ClientSocketPoolManager::set_max_sockets_per_group( 330 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 331 Initialize(false); 332 333 MockWrite writes[] = { 334 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 335 "Host: localhost\r\n" 336 "Connection: keep-alive\r\n\r\n"), 337 MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n" 338 "Host: localhost\r\n" 339 "Connection: keep-alive\r\n\r\n"), 340 MockWrite(SYNCHRONOUS, 8, "GET /three.html HTTP/1.1\r\n" 341 "Host: localhost\r\n" 342 "Connection: keep-alive\r\n\r\n"), 343 MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n" 344 "Host: localhost\r\n" 345 "Connection: keep-alive\r\n\r\n"), 346 }; 347 MockRead reads[] = { 348 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 349 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 350 MockRead(SYNCHRONOUS, 3, "one.html"), 351 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 352 MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), 353 MockRead(SYNCHRONOUS, 7, "two.html"), 354 MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"), 355 MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"), 356 MockRead(SYNCHRONOUS, 11, "three.html"), 357 MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"), 358 MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"), 359 MockRead(SYNCHRONOUS, 15, "four.html"), 360 }; 361 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 362 363 CompleteFourRequests(REQUEST_MAIN_RESOURCE); 364 365 ClientSocketPoolManager::set_max_sockets_per_group( 366 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets); 367 } 368 369 TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) { 370 Initialize(false); 371 372 MockWrite writes[] = { 373 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 374 "Host: localhost\r\n" 375 "Connection: keep-alive\r\n\r\n"), 376 }; 377 MockRead reads[] = { 378 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), 379 MockRead(ASYNC, 2, "one.html"), 380 MockRead(SYNCHRONOUS, OK, 3), 381 }; 382 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 383 384 MockWrite writes2[] = { 385 MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" 386 "Host: localhost\r\n" 387 "Connection: keep-alive\r\n\r\n"), 388 }; 389 MockRead reads2[] = { 390 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 391 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 392 MockRead(SYNCHRONOUS, 3, "two.html"), 393 }; 394 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); 395 396 CompleteTwoRequests(0, 3); 397 } 398 399 TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) { 400 Initialize(false); 401 402 MockWrite writes[] = { 403 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 404 "Host: localhost\r\n" 405 "Connection: keep-alive\r\n\r\n"), 406 MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" 407 "Host: localhost\r\n" 408 "Connection: keep-alive\r\n\r\n"), 409 }; 410 MockRead reads[] = { 411 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 412 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 413 MockRead(ASYNC, 4, "one.html"), 414 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), 415 }; 416 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 417 418 MockWrite writes2[] = { 419 MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" 420 "Host: localhost\r\n" 421 "Connection: keep-alive\r\n\r\n"), 422 }; 423 MockRead reads2[] = { 424 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 425 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 426 MockRead(SYNCHRONOUS, 3, "two.html"), 427 }; 428 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); 429 430 CompleteTwoRequests(0, 5); 431 } 432 433 TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) { 434 Initialize(false); 435 436 MockWrite writes[] = { 437 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 438 "Host: localhost\r\n" 439 "Connection: keep-alive\r\n\r\n"), 440 MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" 441 "Host: localhost\r\n" 442 "Connection: keep-alive\r\n\r\n"), 443 }; 444 MockRead reads[] = { 445 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), 446 MockRead(SYNCHRONOUS, ERR_FAILED, 2), 447 }; 448 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 449 450 MockWrite writes2[] = { 451 MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" 452 "Host: localhost\r\n" 453 "Connection: keep-alive\r\n\r\n"), 454 }; 455 MockRead reads2[] = { 456 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 457 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 458 MockRead(SYNCHRONOUS, 3, "two.html"), 459 }; 460 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); 461 462 HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); 463 TestCompletionCallback one_callback; 464 EXPECT_EQ(ERR_IO_PENDING, 465 one_transaction.Start(GetRequestInfo("one.html"), 466 one_callback.callback(), BoundNetLog())); 467 EXPECT_EQ(OK, one_callback.WaitForResult()); 468 469 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 470 TestCompletionCallback two_callback; 471 EXPECT_EQ(ERR_IO_PENDING, 472 two_transaction.Start(GetRequestInfo("two.html"), 473 two_callback.callback(), BoundNetLog())); 474 475 scoped_refptr<IOBuffer> buffer(new IOBuffer(1)); 476 EXPECT_EQ(ERR_FAILED, 477 one_transaction.Read(buffer.get(), 1, callback_.callback())); 478 EXPECT_EQ(OK, two_callback.WaitForResult()); 479 ExpectResponse("two.html", two_transaction, SYNCHRONOUS); 480 } 481 482 TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) { 483 Initialize(false); 484 485 MockWrite writes[] = { 486 MockWrite(ASYNC, ERR_FAILED, 0), 487 }; 488 AddExpectedConnection(NULL, 0, writes, arraysize(writes)); 489 490 MockWrite writes2[] = { 491 MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" 492 "Host: localhost\r\n" 493 "Connection: keep-alive\r\n\r\n"), 494 }; 495 MockRead reads2[] = { 496 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 497 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 498 MockRead(SYNCHRONOUS, 3, "two.html"), 499 }; 500 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); 501 502 HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); 503 TestCompletionCallback one_callback; 504 EXPECT_EQ(ERR_IO_PENDING, 505 one_transaction.Start(GetRequestInfo("one.html"), 506 one_callback.callback(), BoundNetLog())); 507 508 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 509 TestCompletionCallback two_callback; 510 EXPECT_EQ(ERR_IO_PENDING, 511 two_transaction.Start(GetRequestInfo("two.html"), 512 two_callback.callback(), BoundNetLog())); 513 514 data_vector_[0]->RunFor(1); 515 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); 516 517 EXPECT_EQ(OK, two_callback.WaitForResult()); 518 ExpectResponse("two.html", two_transaction, SYNCHRONOUS); 519 } 520 521 TEST_F(HttpPipelinedNetworkTransactionTest, RedirectDrained) { 522 Initialize(false); 523 524 MockWrite writes[] = { 525 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n" 526 "Host: localhost\r\n" 527 "Connection: keep-alive\r\n\r\n"), 528 MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" 529 "Host: localhost\r\n" 530 "Connection: keep-alive\r\n\r\n"), 531 }; 532 MockRead reads[] = { 533 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 OK\r\n"), 534 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 535 MockRead(ASYNC, 4, "redirect"), 536 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 537 MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), 538 MockRead(SYNCHRONOUS, 7, "two.html"), 539 }; 540 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 541 542 scoped_ptr<HttpNetworkTransaction> one_transaction( 543 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 544 TestCompletionCallback one_callback; 545 EXPECT_EQ(ERR_IO_PENDING, 546 one_transaction->Start(GetRequestInfo("redirect.html"), 547 one_callback.callback(), BoundNetLog())); 548 EXPECT_EQ(OK, one_callback.WaitForResult()); 549 550 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 551 TestCompletionCallback two_callback; 552 EXPECT_EQ(ERR_IO_PENDING, 553 two_transaction.Start(GetRequestInfo("two.html"), 554 two_callback.callback(), BoundNetLog())); 555 556 one_transaction.reset(); 557 data_vector_[0]->RunFor(2); 558 data_vector_[0]->SetStop(10); 559 560 EXPECT_EQ(OK, two_callback.WaitForResult()); 561 ExpectResponse("two.html", two_transaction, SYNCHRONOUS); 562 } 563 564 TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) { 565 Initialize(false); 566 567 MockWrite writes[] = { 568 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 569 "Host: localhost\r\n" 570 "Connection: keep-alive\r\n\r\n"), 571 MockWrite(SYNCHRONOUS, 5, "GET /one.html HTTP/1.1\r\n" 572 "Host: localhost\r\n" 573 "Connection: keep-alive\r\n" 574 "Authorization: auth_token\r\n\r\n"), 575 }; 576 MockRead reads[] = { 577 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Authentication Required\r\n"), 578 MockRead(SYNCHRONOUS, 2, 579 "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"), 580 MockRead(SYNCHRONOUS, 3, "Content-Length: 20\r\n\r\n"), 581 MockRead(SYNCHRONOUS, 4, "needs authentication"), 582 MockRead(SYNCHRONOUS, 6, "HTTP/1.1 200 OK\r\n"), 583 MockRead(SYNCHRONOUS, 7, "Content-Length: 8\r\n\r\n"), 584 MockRead(SYNCHRONOUS, 8, "one.html"), 585 }; 586 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 587 588 HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock; 589 std::string challenge_text = "Basic"; 590 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), 591 challenge_text.end()); 592 GURL origin("localhost"); 593 EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge, 594 HttpAuth::AUTH_SERVER, 595 origin, 596 BoundNetLog())); 597 auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER); 598 599 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get()); 600 EXPECT_EQ(ERR_IO_PENDING, 601 transaction.Start(GetRequestInfo("one.html"), 602 callback_.callback(), 603 BoundNetLog())); 604 EXPECT_EQ(OK, callback_.WaitForResult()); 605 606 AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")); 607 EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, callback_.callback())); 608 609 ExpectResponse("one.html", transaction, SYNCHRONOUS); 610 } 611 612 TEST_F(HttpPipelinedNetworkTransactionTest, OldVersionDisablesPipelining) { 613 Initialize(false); 614 615 MockWrite writes[] = { 616 MockWrite(SYNCHRONOUS, 0, "GET /pipelined.html HTTP/1.1\r\n" 617 "Host: localhost\r\n" 618 "Connection: keep-alive\r\n\r\n"), 619 }; 620 MockRead reads[] = { 621 MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"), 622 MockRead(SYNCHRONOUS, 2, "Content-Length: 14\r\n\r\n"), 623 MockRead(SYNCHRONOUS, 3, "pipelined.html"), 624 }; 625 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 626 627 MockWrite writes2[] = { 628 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 629 "Host: localhost\r\n" 630 "Connection: keep-alive\r\n\r\n"), 631 }; 632 MockRead reads2[] = { 633 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 634 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 635 MockRead(ASYNC, 3, "one.html"), 636 MockRead(SYNCHRONOUS, OK, 4), 637 }; 638 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); 639 640 MockWrite writes3[] = { 641 MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" 642 "Host: localhost\r\n" 643 "Connection: keep-alive\r\n\r\n"), 644 }; 645 MockRead reads3[] = { 646 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 647 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 648 MockRead(SYNCHRONOUS, 3, "two.html"), 649 MockRead(SYNCHRONOUS, OK, 4), 650 }; 651 AddExpectedConnection(reads3, arraysize(reads3), writes3, arraysize(writes3)); 652 653 HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); 654 TestCompletionCallback one_callback; 655 EXPECT_EQ(ERR_IO_PENDING, 656 one_transaction.Start(GetRequestInfo("pipelined.html"), 657 one_callback.callback(), BoundNetLog())); 658 EXPECT_EQ(OK, one_callback.WaitForResult()); 659 ExpectResponse("pipelined.html", one_transaction, SYNCHRONOUS); 660 661 CompleteTwoRequests(1, 4); 662 } 663 664 TEST_F(HttpPipelinedNetworkTransactionTest, PipelinesImmediatelyIfKnownGood) { 665 // The first request gets us an HTTP/1.1. The next 3 test pipelining. When the 666 // 3rd request completes, we know pipelining is safe. After the first 4 667 // complete, the 5th and 6th should then be immediately sent pipelined on a 668 // new HttpPipelinedConnection. 669 int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group( 670 HttpNetworkSession::NORMAL_SOCKET_POOL); 671 ClientSocketPoolManager::set_max_sockets_per_group( 672 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 673 Initialize(false); 674 675 MockWrite writes[] = { 676 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 677 "Host: localhost\r\n" 678 "Connection: keep-alive\r\n\r\n"), 679 MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n" 680 "Host: localhost\r\n" 681 "Connection: keep-alive\r\n\r\n"), 682 MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n" 683 "Host: localhost\r\n" 684 "Connection: keep-alive\r\n\r\n"), 685 MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n" 686 "Host: localhost\r\n" 687 "Connection: keep-alive\r\n\r\n"), 688 MockWrite(SYNCHRONOUS, 16, "GET /second-pipeline-one.html HTTP/1.1\r\n" 689 "Host: localhost\r\n" 690 "Connection: keep-alive\r\n\r\n"), 691 MockWrite(SYNCHRONOUS, 17, "GET /second-pipeline-two.html HTTP/1.1\r\n" 692 "Host: localhost\r\n" 693 "Connection: keep-alive\r\n\r\n"), 694 }; 695 MockRead reads[] = { 696 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 697 MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), 698 MockRead(SYNCHRONOUS, 3, "one.html"), 699 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 700 MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), 701 MockRead(SYNCHRONOUS, 8, "two.html"), 702 MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"), 703 MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"), 704 MockRead(SYNCHRONOUS, 11, "three.html"), 705 MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"), 706 MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"), 707 MockRead(SYNCHRONOUS, 15, "four.html"), 708 MockRead(ASYNC, 18, "HTTP/1.1 200 OK\r\n"), 709 MockRead(ASYNC, 19, "Content-Length: 24\r\n\r\n"), 710 MockRead(SYNCHRONOUS, 20, "second-pipeline-one.html"), 711 MockRead(SYNCHRONOUS, 21, "HTTP/1.1 200 OK\r\n"), 712 MockRead(SYNCHRONOUS, 22, "Content-Length: 24\r\n\r\n"), 713 MockRead(SYNCHRONOUS, 23, "second-pipeline-two.html"), 714 }; 715 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 716 717 CompleteFourRequests(REQUEST_DEFAULT); 718 719 HttpNetworkTransaction second_one_transaction( 720 DEFAULT_PRIORITY, session_.get()); 721 TestCompletionCallback second_one_callback; 722 EXPECT_EQ(ERR_IO_PENDING, 723 second_one_transaction.Start( 724 GetRequestInfo("second-pipeline-one.html"), 725 second_one_callback.callback(), BoundNetLog())); 726 base::MessageLoop::current()->RunUntilIdle(); 727 728 HttpNetworkTransaction second_two_transaction( 729 DEFAULT_PRIORITY, session_.get()); 730 TestCompletionCallback second_two_callback; 731 EXPECT_EQ(ERR_IO_PENDING, 732 second_two_transaction.Start( 733 GetRequestInfo("second-pipeline-two.html"), 734 second_two_callback.callback(), BoundNetLog())); 735 736 data_vector_[0]->RunFor(3); 737 EXPECT_EQ(OK, second_one_callback.WaitForResult()); 738 data_vector_[0]->StopAfter(100); 739 ExpectResponse("second-pipeline-one.html", second_one_transaction, 740 SYNCHRONOUS); 741 EXPECT_EQ(OK, second_two_callback.WaitForResult()); 742 ExpectResponse("second-pipeline-two.html", second_two_transaction, 743 SYNCHRONOUS); 744 745 ClientSocketPoolManager::set_max_sockets_per_group( 746 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets); 747 } 748 749 class DataRunnerObserver : public base::MessageLoop::TaskObserver { 750 public: 751 DataRunnerObserver(DeterministicSocketData* data, int run_before_task) 752 : data_(data), 753 run_before_task_(run_before_task), 754 current_task_(0) { } 755 756 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE { 757 ++current_task_; 758 if (current_task_ == run_before_task_) { 759 data_->Run(); 760 base::MessageLoop::current()->RemoveTaskObserver(this); 761 } 762 } 763 764 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {} 765 766 private: 767 DeterministicSocketData* data_; 768 int run_before_task_; 769 int current_task_; 770 }; 771 772 TEST_F(HttpPipelinedNetworkTransactionTest, OpenPipelinesWhileBinding) { 773 // There was a racy crash in the pipelining code. This test recreates that 774 // race. The steps are: 775 // 1. The first request starts a pipeline and requests headers. 776 // 2. HttpStreamFactoryImpl::Job tries to bind a pending request to a new 777 // pipeline and queues a task to do so. 778 // 3. Before that task runs, the first request receives its headers and 779 // determines this host is probably capable of pipelining. 780 // 4. All of the hosts' pipelines are notified they have capacity in a loop. 781 // 5. On the first iteration, the first pipeline is opened up to accept new 782 // requests and steals the request from step #2. 783 // 6. The pipeline from #2 is deleted because it has no streams. 784 // 7. On the second iteration, the host tries to notify the pipeline from step 785 // #2 that it has capacity. This is a use-after-free. 786 Initialize(false); 787 788 MockWrite writes[] = { 789 MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" 790 "Host: localhost\r\n" 791 "Connection: keep-alive\r\n\r\n"), 792 MockWrite(ASYNC, 3, "GET /two.html HTTP/1.1\r\n" 793 "Host: localhost\r\n" 794 "Connection: keep-alive\r\n\r\n"), 795 }; 796 MockRead reads[] = { 797 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 798 MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"), 799 MockRead(SYNCHRONOUS, 4, "one.html"), 800 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 801 MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), 802 MockRead(SYNCHRONOUS, 7, "two.html"), 803 }; 804 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 805 806 AddExpectedConnection(NULL, 0, NULL, 0); 807 808 HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); 809 TestCompletionCallback one_callback; 810 EXPECT_EQ(ERR_IO_PENDING, 811 one_transaction.Start(GetRequestInfo("one.html"), 812 one_callback.callback(), BoundNetLog())); 813 814 data_vector_[0]->SetStop(2); 815 data_vector_[0]->Run(); 816 817 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 818 TestCompletionCallback two_callback; 819 EXPECT_EQ(ERR_IO_PENDING, 820 two_transaction.Start(GetRequestInfo("two.html"), 821 two_callback.callback(), BoundNetLog())); 822 // Posted tasks should be: 823 // 1. MockHostResolverBase::ResolveNow 824 // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1 825 // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2 826 // 827 // We need to make sure that the response that triggers OnPipelineFeedback(OK) 828 // is called in between when task #3 is scheduled and when it runs. The 829 // DataRunnerObserver does that. 830 DataRunnerObserver observer(data_vector_[0], 3); 831 base::MessageLoop::current()->AddTaskObserver(&observer); 832 data_vector_[0]->SetStop(4); 833 base::MessageLoop::current()->RunUntilIdle(); 834 data_vector_[0]->SetStop(10); 835 836 EXPECT_EQ(OK, one_callback.WaitForResult()); 837 ExpectResponse("one.html", one_transaction, SYNCHRONOUS); 838 EXPECT_EQ(OK, two_callback.WaitForResult()); 839 ExpectResponse("two.html", two_transaction, SYNCHRONOUS); 840 } 841 842 TEST_F(HttpPipelinedNetworkTransactionTest, ProxyChangesWhileConnecting) { 843 Initialize(false); 844 845 DeterministicSocketData data(NULL, 0, NULL, 0); 846 data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED)); 847 factory_.AddSocketDataProvider(&data); 848 849 DeterministicSocketData data2(NULL, 0, NULL, 0); 850 data2.set_connect_data(MockConnect(ASYNC, ERR_FAILED)); 851 factory_.AddSocketDataProvider(&data2); 852 853 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get()); 854 EXPECT_EQ(ERR_IO_PENDING, 855 transaction.Start(GetRequestInfo("test.html"), callback_.callback(), 856 BoundNetLog())); 857 858 proxy_config_service_->IncrementConfigId(); 859 860 EXPECT_EQ(ERR_FAILED, callback_.WaitForResult()); 861 } 862 863 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineSharesConnection) { 864 Initialize(true); 865 866 MockWrite writes[] = { 867 MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n" 868 "Host: localhost\r\n" 869 "Connection: keep-alive\r\n\r\n" 870 "GET /two.html HTTP/1.1\r\n" 871 "Host: localhost\r\n" 872 "Connection: keep-alive\r\n\r\n"), 873 }; 874 MockRead reads[] = { 875 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 876 MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"), 877 MockRead(ASYNC, 3, "one.html"), 878 MockRead(ASYNC, 4, "HTTP/1.1 200 OK\r\n"), 879 MockRead(ASYNC, 5, "Content-Length: 8\r\n\r\n"), 880 MockRead(ASYNC, 6, "two.html"), 881 }; 882 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 883 884 scoped_ptr<HttpNetworkTransaction> one_transaction( 885 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 886 TestCompletionCallback one_callback; 887 EXPECT_EQ(ERR_IO_PENDING, 888 one_transaction->Start(GetRequestInfo("one.html"), 889 one_callback.callback(), BoundNetLog())); 890 891 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 892 TestCompletionCallback two_callback; 893 EXPECT_EQ(ERR_IO_PENDING, 894 two_transaction.Start(GetRequestInfo("two.html"), 895 two_callback.callback(), BoundNetLog())); 896 897 data_vector_[0]->RunFor(3); // Send + 2 lines of headers. 898 EXPECT_EQ(OK, one_callback.WaitForResult()); 899 ExpectResponse("one.html", *one_transaction.get(), ASYNC); 900 one_transaction.reset(); 901 902 data_vector_[0]->RunFor(2); // 2 lines of headers. 903 EXPECT_EQ(OK, two_callback.WaitForResult()); 904 ExpectResponse("two.html", two_transaction, ASYNC); 905 } 906 907 TEST_F(HttpPipelinedNetworkTransactionTest, 908 ForcedPipelineConnectionErrorFailsBoth) { 909 Initialize(true); 910 911 DeterministicSocketData data(NULL, 0, NULL, 0); 912 data.set_connect_data(MockConnect(ASYNC, ERR_FAILED)); 913 factory_.AddSocketDataProvider(&data); 914 915 scoped_ptr<HttpNetworkTransaction> one_transaction( 916 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 917 TestCompletionCallback one_callback; 918 EXPECT_EQ(ERR_IO_PENDING, 919 one_transaction->Start(GetRequestInfo("one.html"), 920 one_callback.callback(), BoundNetLog())); 921 922 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 923 TestCompletionCallback two_callback; 924 EXPECT_EQ(ERR_IO_PENDING, 925 two_transaction.Start(GetRequestInfo("two.html"), 926 two_callback.callback(), BoundNetLog())); 927 928 data.Run(); 929 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); 930 EXPECT_EQ(ERR_FAILED, two_callback.WaitForResult()); 931 } 932 933 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineEvictionIsFatal) { 934 Initialize(true); 935 936 MockWrite writes[] = { 937 MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n" 938 "Host: localhost\r\n" 939 "Connection: keep-alive\r\n\r\n" 940 "GET /two.html HTTP/1.1\r\n" 941 "Host: localhost\r\n" 942 "Connection: keep-alive\r\n\r\n"), 943 }; 944 MockRead reads[] = { 945 MockRead(ASYNC, ERR_FAILED, 1), 946 }; 947 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); 948 949 scoped_ptr<HttpNetworkTransaction> one_transaction( 950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 951 TestCompletionCallback one_callback; 952 EXPECT_EQ(ERR_IO_PENDING, 953 one_transaction->Start(GetRequestInfo("one.html"), 954 one_callback.callback(), BoundNetLog())); 955 956 HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); 957 TestCompletionCallback two_callback; 958 EXPECT_EQ(ERR_IO_PENDING, 959 two_transaction.Start(GetRequestInfo("two.html"), 960 two_callback.callback(), BoundNetLog())); 961 962 data_vector_[0]->RunFor(2); 963 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); 964 one_transaction.reset(); 965 EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult()); 966 } 967 968 TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineOrder) { 969 Initialize(true); 970 971 MockWrite writes[] = { 972 MockWrite(ASYNC, 0, 973 "GET /one.html HTTP/1.1\r\n" 974 "Host: localhost\r\n" 975 "Connection: keep-alive\r\n\r\n" 976 "GET /two.html HTTP/1.1\r\n" 977 "Host: localhost\r\n" 978 "Connection: keep-alive\r\n\r\n" 979 "GET /three.html HTTP/1.1\r\n" 980 "Host: localhost\r\n" 981 "Connection: keep-alive\r\n\r\n" 982 "GET /four.html HTTP/1.1\r\n" 983 "Host: localhost\r\n" 984 "Connection: keep-alive\r\n\r\n" 985 ), 986 }; 987 MockRead reads[] = { 988 MockRead(ASYNC, ERR_FAILED, 1), 989 }; 990 DeterministicSocketData data( 991 reads, arraysize(reads), writes, arraysize(writes)); 992 data.set_connect_data(MockConnect(ASYNC, OK)); 993 factory_.AddSocketDataProvider(&data); 994 995 scoped_ptr<HttpNetworkTransaction> one_transaction( 996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 997 TestCompletionCallback one_callback; 998 EXPECT_EQ(ERR_IO_PENDING, 999 one_transaction->Start(GetRequestInfo("one.html"), 1000 one_callback.callback(), BoundNetLog())); 1001 1002 scoped_ptr<HttpNetworkTransaction> two_transaction( 1003 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 1004 TestCompletionCallback two_callback; 1005 EXPECT_EQ(ERR_IO_PENDING, 1006 two_transaction->Start(GetRequestInfo("two.html"), 1007 two_callback.callback(), BoundNetLog())); 1008 1009 scoped_ptr<HttpNetworkTransaction> three_transaction( 1010 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 1011 TestCompletionCallback three_callback; 1012 EXPECT_EQ(ERR_IO_PENDING, 1013 three_transaction->Start(GetRequestInfo("three.html"), 1014 three_callback.callback(), BoundNetLog())); 1015 1016 scoped_ptr<HttpNetworkTransaction> four_transaction( 1017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); 1018 TestCompletionCallback four_callback; 1019 EXPECT_EQ(ERR_IO_PENDING, 1020 four_transaction->Start(GetRequestInfo("four.html"), 1021 four_callback.callback(), BoundNetLog())); 1022 1023 data.RunFor(3); 1024 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); 1025 one_transaction.reset(); 1026 EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult()); 1027 two_transaction.reset(); 1028 EXPECT_EQ(ERR_PIPELINE_EVICTION, three_callback.WaitForResult()); 1029 three_transaction.reset(); 1030 EXPECT_EQ(ERR_PIPELINE_EVICTION, four_callback.WaitForResult()); 1031 } 1032 1033 } // anonymous namespace 1034 1035 } // namespace net 1036