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_connection_impl.h" 6 7 #include <string> 8 9 #include "base/memory/ref_counted.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_vector.h" 12 #include "net/base/capturing_net_log.h" 13 #include "net/base/io_buffer.h" 14 #include "net/base/load_timing_info.h" 15 #include "net/base/load_timing_info_test_util.h" 16 #include "net/base/net_errors.h" 17 #include "net/base/request_priority.h" 18 #include "net/http/http_pipelined_stream.h" 19 #include "net/socket/client_socket_handle.h" 20 #include "net/socket/client_socket_pool_histograms.h" 21 #include "net/socket/socket_test_util.h" 22 #include "testing/gmock/include/gmock/gmock.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 using testing::_; 26 using testing::NiceMock; 27 using testing::StrEq; 28 29 namespace net { 30 31 class DummySocketParams : public base::RefCounted<DummySocketParams> { 32 private: 33 friend class base::RefCounted<DummySocketParams>; 34 ~DummySocketParams() {} 35 }; 36 37 REGISTER_SOCKET_PARAMS_FOR_POOL(MockTransportClientSocketPool, 38 DummySocketParams); 39 40 namespace { 41 42 // Tests the load timing of a stream that's connected and is not the first 43 // request sent on a connection. 44 void TestLoadTimingReused(const HttpStream& stream) { 45 LoadTimingInfo load_timing_info; 46 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); 47 48 EXPECT_TRUE(load_timing_info.socket_reused); 49 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 50 51 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 52 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); 53 } 54 55 // Tests the load timing of a stream that's connected and using a fresh 56 // connection. 57 void TestLoadTimingNotReused(const HttpStream& stream) { 58 LoadTimingInfo load_timing_info; 59 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); 60 61 EXPECT_FALSE(load_timing_info.socket_reused); 62 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 63 64 ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 65 CONNECT_TIMING_HAS_DNS_TIMES); 66 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); 67 } 68 69 class MockPipelineDelegate : public HttpPipelinedConnection::Delegate { 70 public: 71 MOCK_METHOD1(OnPipelineHasCapacity, void(HttpPipelinedConnection* pipeline)); 72 MOCK_METHOD2(OnPipelineFeedback, void( 73 HttpPipelinedConnection* pipeline, 74 HttpPipelinedConnection::Feedback feedback)); 75 }; 76 77 class SuddenCloseObserver : public base::MessageLoop::TaskObserver { 78 public: 79 SuddenCloseObserver(HttpStream* stream, int close_before_task) 80 : stream_(stream), 81 close_before_task_(close_before_task), 82 current_task_(0) { } 83 84 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE { 85 ++current_task_; 86 if (current_task_ == close_before_task_) { 87 stream_->Close(false); 88 base::MessageLoop::current()->RemoveTaskObserver(this); 89 } 90 } 91 92 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {} 93 94 private: 95 HttpStream* stream_; 96 int close_before_task_; 97 int current_task_; 98 }; 99 100 class HttpPipelinedConnectionImplTest : public testing::Test { 101 public: 102 HttpPipelinedConnectionImplTest() 103 : histograms_("a"), 104 pool_(1, 1, &histograms_, &factory_), 105 origin_("host", 123) { 106 } 107 108 void TearDown() { 109 base::MessageLoop::current()->RunUntilIdle(); 110 } 111 112 void Initialize(MockRead* reads, size_t reads_count, 113 MockWrite* writes, size_t writes_count) { 114 data_.reset(new DeterministicSocketData(reads, reads_count, 115 writes, writes_count)); 116 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 117 if (reads_count || writes_count) { 118 data_->StopAfter(reads_count + writes_count); 119 } 120 factory_.AddSocketDataProvider(data_.get()); 121 scoped_refptr<DummySocketParams> params; 122 ClientSocketHandle* connection = new ClientSocketHandle; 123 // Only give the connection a real NetLog to make sure that LoadTiming uses 124 // the connection's ID, rather than the pipeline's. Since pipelines are 125 // destroyed when they've responded to all requests, but the connection 126 // lives on, this is an important behavior. 127 connection->Init("a", params, MEDIUM, CompletionCallback(), &pool_, 128 net_log_.bound()); 129 pipeline_.reset(new HttpPipelinedConnectionImpl( 130 connection, &delegate_, origin_, ssl_config_, proxy_info_, 131 BoundNetLog(), false, kProtoUnknown)); 132 } 133 134 HttpRequestInfo* GetRequestInfo(const std::string& filename) { 135 HttpRequestInfo* request_info = new HttpRequestInfo; 136 request_info->url = GURL("http://localhost/" + filename); 137 request_info->method = "GET"; 138 request_info_vector_.push_back(request_info); 139 return request_info; 140 } 141 142 HttpStream* NewTestStream(const std::string& filename) { 143 HttpStream* stream = pipeline_->CreateNewStream(); 144 HttpRequestInfo* request_info = GetRequestInfo(filename); 145 int rv = stream->InitializeStream( 146 request_info, DEFAULT_PRIORITY, BoundNetLog(), CompletionCallback()); 147 DCHECK_EQ(OK, rv); 148 return stream; 149 } 150 151 void ExpectResponse(const std::string& expected, 152 scoped_ptr<HttpStream>& stream, bool async) { 153 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); 154 155 if (async) { 156 EXPECT_EQ(ERR_IO_PENDING, 157 stream->ReadResponseBody(buffer.get(), expected.size(), 158 callback_.callback())); 159 data_->RunFor(1); 160 EXPECT_EQ(static_cast<int>(expected.size()), callback_.WaitForResult()); 161 } else { 162 EXPECT_EQ(static_cast<int>(expected.size()), 163 stream->ReadResponseBody(buffer.get(), expected.size(), 164 callback_.callback())); 165 } 166 std::string actual(buffer->data(), expected.size()); 167 EXPECT_THAT(actual, StrEq(expected)); 168 } 169 170 void TestSyncRequest(scoped_ptr<HttpStream>& stream, 171 const std::string& filename) { 172 HttpRequestHeaders headers; 173 HttpResponseInfo response; 174 EXPECT_EQ(OK, stream->SendRequest(headers, &response, 175 callback_.callback())); 176 EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); 177 ExpectResponse(filename, stream, false); 178 179 stream->Close(false); 180 } 181 182 CapturingBoundNetLog net_log_; 183 DeterministicMockClientSocketFactory factory_; 184 ClientSocketPoolHistograms histograms_; 185 MockTransportClientSocketPool pool_; 186 scoped_ptr<DeterministicSocketData> data_; 187 188 HostPortPair origin_; 189 SSLConfig ssl_config_; 190 ProxyInfo proxy_info_; 191 NiceMock<MockPipelineDelegate> delegate_; 192 TestCompletionCallback callback_; 193 scoped_ptr<HttpPipelinedConnectionImpl> pipeline_; 194 ScopedVector<HttpRequestInfo> request_info_vector_; 195 }; 196 197 TEST_F(HttpPipelinedConnectionImplTest, PipelineNotUsed) { 198 Initialize(NULL, 0, NULL, 0); 199 } 200 201 TEST_F(HttpPipelinedConnectionImplTest, StreamNotUsed) { 202 Initialize(NULL, 0, NULL, 0); 203 204 scoped_ptr<HttpStream> stream(pipeline_->CreateNewStream()); 205 206 stream->Close(false); 207 } 208 209 TEST_F(HttpPipelinedConnectionImplTest, StreamBoundButNotUsed) { 210 Initialize(NULL, 0, NULL, 0); 211 212 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 213 214 TestLoadTimingNotReused(*stream); 215 stream->Close(false); 216 TestLoadTimingNotReused(*stream); 217 } 218 219 TEST_F(HttpPipelinedConnectionImplTest, SyncSingleRequest) { 220 MockWrite writes[] = { 221 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 222 }; 223 MockRead reads[] = { 224 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 225 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), 226 MockRead(SYNCHRONOUS, 3, "ok.html"), 227 }; 228 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 229 230 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 231 TestLoadTimingNotReused(*stream); 232 TestSyncRequest(stream, "ok.html"); 233 TestLoadTimingNotReused(*stream); 234 } 235 236 TEST_F(HttpPipelinedConnectionImplTest, AsyncSingleRequest) { 237 MockWrite writes[] = { 238 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 239 }; 240 MockRead reads[] = { 241 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 242 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), 243 MockRead(ASYNC, 3, "ok.html"), 244 }; 245 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 246 247 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 248 249 HttpRequestHeaders headers; 250 HttpResponseInfo response; 251 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response, 252 callback_.callback())); 253 data_->RunFor(1); 254 EXPECT_LE(OK, callback_.WaitForResult()); 255 TestLoadTimingNotReused(*stream); 256 257 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); 258 data_->RunFor(2); 259 EXPECT_LE(OK, callback_.WaitForResult()); 260 TestLoadTimingNotReused(*stream); 261 262 ExpectResponse("ok.html", stream, true); 263 TestLoadTimingNotReused(*stream); 264 265 stream->Close(false); 266 } 267 268 TEST_F(HttpPipelinedConnectionImplTest, LockStepAsyncRequests) { 269 MockWrite writes[] = { 270 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 271 MockWrite(ASYNC, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), 272 }; 273 MockRead reads[] = { 274 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"), 275 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), 276 MockRead(ASYNC, 4, "ok.html"), 277 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), 278 MockRead(ASYNC, 6, "Content-Length: 7\r\n\r\n"), 279 MockRead(ASYNC, 7, "ko.html"), 280 }; 281 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 282 283 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 284 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 285 286 HttpRequestHeaders headers1; 287 HttpResponseInfo response1; 288 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(headers1, &response1, 289 callback_.callback())); 290 TestLoadTimingNotReused(*stream1); 291 292 HttpRequestHeaders headers2; 293 HttpResponseInfo response2; 294 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2, 295 callback_.callback())); 296 TestLoadTimingReused(*stream2); 297 298 data_->RunFor(1); 299 EXPECT_LE(OK, callback_.WaitForResult()); 300 data_->RunFor(1); 301 EXPECT_LE(OK, callback_.WaitForResult()); 302 303 EXPECT_EQ(ERR_IO_PENDING, stream1->ReadResponseHeaders(callback_.callback())); 304 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback_.callback())); 305 306 data_->RunFor(2); 307 EXPECT_LE(OK, callback_.WaitForResult()); 308 309 ExpectResponse("ok.html", stream1, true); 310 311 TestLoadTimingNotReused(*stream1); 312 LoadTimingInfo load_timing_info1; 313 EXPECT_TRUE(stream1->GetLoadTimingInfo(&load_timing_info1)); 314 stream1->Close(false); 315 316 data_->RunFor(2); 317 EXPECT_LE(OK, callback_.WaitForResult()); 318 319 ExpectResponse("ko.html", stream2, true); 320 321 TestLoadTimingReused(*stream2); 322 LoadTimingInfo load_timing_info2; 323 EXPECT_TRUE(stream2->GetLoadTimingInfo(&load_timing_info2)); 324 EXPECT_EQ(load_timing_info1.socket_log_id, 325 load_timing_info2.socket_log_id); 326 stream2->Close(false); 327 } 328 329 TEST_F(HttpPipelinedConnectionImplTest, TwoResponsesInOnePacket) { 330 MockWrite writes[] = { 331 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 332 MockWrite(SYNCHRONOUS, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), 333 }; 334 MockRead reads[] = { 335 MockRead(SYNCHRONOUS, 2, 336 "HTTP/1.1 200 OK\r\n" 337 "Content-Length: 7\r\n\r\n" 338 "ok.html" 339 "HTTP/1.1 200 OK\r\n" 340 "Content-Length: 7\r\n\r\n" 341 "ko.html"), 342 }; 343 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 344 345 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 346 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 347 348 HttpRequestHeaders headers1; 349 HttpResponseInfo response1; 350 EXPECT_EQ(OK, stream1->SendRequest(headers1, 351 &response1, callback_.callback())); 352 HttpRequestHeaders headers2; 353 HttpResponseInfo response2; 354 EXPECT_EQ(OK, stream2->SendRequest(headers2, 355 &response2, callback_.callback())); 356 357 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 358 ExpectResponse("ok.html", stream1, false); 359 stream1->Close(false); 360 361 EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback())); 362 ExpectResponse("ko.html", stream2, false); 363 stream2->Close(false); 364 } 365 366 TEST_F(HttpPipelinedConnectionImplTest, SendOrderSwapped) { 367 MockWrite writes[] = { 368 MockWrite(SYNCHRONOUS, 0, "GET /ko.html HTTP/1.1\r\n\r\n"), 369 MockWrite(SYNCHRONOUS, 4, "GET /ok.html HTTP/1.1\r\n\r\n"), 370 }; 371 MockRead reads[] = { 372 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 373 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), 374 MockRead(SYNCHRONOUS, 3, "ko.html"), 375 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 376 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), 377 MockRead(SYNCHRONOUS, 7, "ok.html"), 378 }; 379 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 380 381 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 382 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 383 384 TestSyncRequest(stream2, "ko.html"); 385 TestSyncRequest(stream1, "ok.html"); 386 TestLoadTimingNotReused(*stream1); 387 TestLoadTimingReused(*stream2); 388 } 389 390 TEST_F(HttpPipelinedConnectionImplTest, ReadOrderSwapped) { 391 MockWrite writes[] = { 392 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 393 MockWrite(SYNCHRONOUS, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), 394 }; 395 MockRead reads[] = { 396 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 397 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), 398 MockRead(SYNCHRONOUS, 4, "ok.html"), 399 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 400 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), 401 MockRead(SYNCHRONOUS, 7, "ko.html"), 402 }; 403 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 404 405 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 406 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 407 408 HttpRequestHeaders headers1; 409 HttpResponseInfo response1; 410 EXPECT_EQ(OK, stream1->SendRequest(headers1, 411 &response1, callback_.callback())); 412 413 HttpRequestHeaders headers2; 414 HttpResponseInfo response2; 415 EXPECT_EQ(OK, stream2->SendRequest(headers2, 416 &response2, callback_.callback())); 417 418 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback_.callback())); 419 420 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 421 ExpectResponse("ok.html", stream1, false); 422 423 stream1->Close(false); 424 425 EXPECT_LE(OK, callback_.WaitForResult()); 426 ExpectResponse("ko.html", stream2, false); 427 428 stream2->Close(false); 429 } 430 431 TEST_F(HttpPipelinedConnectionImplTest, SendWhileReading) { 432 MockWrite writes[] = { 433 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 434 MockWrite(SYNCHRONOUS, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), 435 }; 436 MockRead reads[] = { 437 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 438 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), 439 MockRead(SYNCHRONOUS, 4, "ok.html"), 440 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 441 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), 442 MockRead(SYNCHRONOUS, 7, "ko.html"), 443 }; 444 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 445 446 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 447 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 448 449 HttpRequestHeaders headers1; 450 HttpResponseInfo response1; 451 EXPECT_EQ(OK, stream1->SendRequest(headers1, 452 &response1, callback_.callback())); 453 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 454 455 HttpRequestHeaders headers2; 456 HttpResponseInfo response2; 457 EXPECT_EQ(OK, stream2->SendRequest(headers2, 458 &response2, callback_.callback())); 459 460 ExpectResponse("ok.html", stream1, false); 461 stream1->Close(false); 462 463 EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback())); 464 ExpectResponse("ko.html", stream2, false); 465 stream2->Close(false); 466 } 467 468 TEST_F(HttpPipelinedConnectionImplTest, AsyncSendWhileAsyncReadBlocked) { 469 MockWrite writes[] = { 470 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 471 MockWrite(ASYNC, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), 472 }; 473 MockRead reads[] = { 474 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 475 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), 476 MockRead(ASYNC, 4, "ok.html"), 477 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 478 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), 479 MockRead(SYNCHRONOUS, 7, "ko.html"), 480 }; 481 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 482 483 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 484 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 485 486 HttpRequestHeaders headers1; 487 HttpResponseInfo response1; 488 EXPECT_EQ(OK, stream1->SendRequest(headers1, 489 &response1, callback_.callback())); 490 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 491 TestCompletionCallback callback1; 492 std::string expected = "ok.html"; 493 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); 494 EXPECT_EQ(ERR_IO_PENDING, 495 stream1->ReadResponseBody(buffer.get(), expected.size(), 496 callback1.callback())); 497 498 HttpRequestHeaders headers2; 499 HttpResponseInfo response2; 500 TestCompletionCallback callback2; 501 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2, 502 callback2.callback())); 503 504 data_->RunFor(1); 505 EXPECT_LE(OK, callback2.WaitForResult()); 506 EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback2.callback())); 507 508 data_->RunFor(1); 509 EXPECT_EQ(static_cast<int>(expected.size()), callback1.WaitForResult()); 510 std::string actual(buffer->data(), expected.size()); 511 EXPECT_THAT(actual, StrEq(expected)); 512 stream1->Close(false); 513 514 data_->StopAfter(8); 515 EXPECT_LE(OK, callback2.WaitForResult()); 516 ExpectResponse("ko.html", stream2, false); 517 stream2->Close(false); 518 } 519 520 TEST_F(HttpPipelinedConnectionImplTest, UnusedStreamAllowsLaterUse) { 521 MockWrite writes[] = { 522 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 523 }; 524 MockRead reads[] = { 525 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 526 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"), 527 MockRead(SYNCHRONOUS, 3, "ok.html"), 528 }; 529 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 530 531 scoped_ptr<HttpStream> unused_stream(NewTestStream("unused.html")); 532 unused_stream->Close(false); 533 534 scoped_ptr<HttpStream> later_stream(NewTestStream("ok.html")); 535 TestSyncRequest(later_stream, "ok.html"); 536 } 537 538 TEST_F(HttpPipelinedConnectionImplTest, UnsentStreamAllowsLaterUse) { 539 MockWrite writes[] = { 540 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 541 MockWrite(SYNCHRONOUS, 4, "GET /ko.html HTTP/1.1\r\n\r\n"), 542 }; 543 MockRead reads[] = { 544 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), 545 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), 546 MockRead(ASYNC, 3, "ok.html"), 547 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), 548 MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"), 549 MockRead(SYNCHRONOUS, 7, "ko.html"), 550 }; 551 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 552 553 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 554 555 HttpRequestHeaders headers; 556 HttpResponseInfo response; 557 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response, 558 callback_.callback())); 559 560 scoped_ptr<HttpStream> unsent_stream(NewTestStream("unsent.html")); 561 HttpRequestHeaders unsent_headers; 562 HttpResponseInfo unsent_response; 563 EXPECT_EQ(ERR_IO_PENDING, unsent_stream->SendRequest(unsent_headers, 564 &unsent_response, 565 callback_.callback())); 566 unsent_stream->Close(false); 567 568 data_->RunFor(1); 569 EXPECT_LE(OK, callback_.WaitForResult()); 570 571 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); 572 data_->RunFor(2); 573 EXPECT_LE(OK, callback_.WaitForResult()); 574 575 ExpectResponse("ok.html", stream, true); 576 577 stream->Close(false); 578 579 data_->StopAfter(8); 580 scoped_ptr<HttpStream> later_stream(NewTestStream("ko.html")); 581 TestSyncRequest(later_stream, "ko.html"); 582 } 583 584 TEST_F(HttpPipelinedConnectionImplTest, FailedSend) { 585 MockWrite writes[] = { 586 MockWrite(ASYNC, ERR_FAILED), 587 }; 588 Initialize(NULL, 0, writes, arraysize(writes)); 589 590 scoped_ptr<HttpStream> failed_stream(NewTestStream("ok.html")); 591 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 592 scoped_ptr<HttpStream> closed_stream(NewTestStream("closed.html")); 593 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); 594 595 HttpRequestHeaders headers; 596 HttpResponseInfo response; 597 TestCompletionCallback failed_callback; 598 EXPECT_EQ(ERR_IO_PENDING, 599 failed_stream->SendRequest(headers, &response, 600 failed_callback.callback())); 601 TestCompletionCallback evicted_callback; 602 EXPECT_EQ(ERR_IO_PENDING, 603 evicted_stream->SendRequest(headers, &response, 604 evicted_callback.callback())); 605 EXPECT_EQ(ERR_IO_PENDING, closed_stream->SendRequest(headers, &response, 606 callback_.callback())); 607 closed_stream->Close(false); 608 609 data_->RunFor(1); 610 EXPECT_EQ(ERR_FAILED, failed_callback.WaitForResult()); 611 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 612 EXPECT_EQ(ERR_PIPELINE_EVICTION, 613 rejected_stream->SendRequest(headers, &response, 614 callback_.callback())); 615 616 failed_stream->Close(true); 617 evicted_stream->Close(true); 618 rejected_stream->Close(true); 619 } 620 621 TEST_F(HttpPipelinedConnectionImplTest, ConnectionSuddenlyClosedAfterResponse) { 622 MockWrite writes[] = { 623 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 624 MockWrite(SYNCHRONOUS, 1, "GET /read_evicted.html HTTP/1.1\r\n\r\n"), 625 MockWrite(SYNCHRONOUS, 2, "GET /read_rejected.html HTTP/1.1\r\n\r\n"), 626 MockWrite(ASYNC, ERR_SOCKET_NOT_CONNECTED, 5), 627 }; 628 MockRead reads[] = { 629 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n\r\n"), 630 MockRead(SYNCHRONOUS, 4, "ok.html"), 631 MockRead(ASYNC, OK, 6), // Connection closed message. Not read before the 632 // ERR_SOCKET_NOT_CONNECTED. 633 }; 634 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 635 636 scoped_ptr<HttpStream> closed_stream(NewTestStream("ok.html")); 637 scoped_ptr<HttpStream> read_evicted_stream( 638 NewTestStream("read_evicted.html")); 639 scoped_ptr<HttpStream> read_rejected_stream( 640 NewTestStream("read_rejected.html")); 641 scoped_ptr<HttpStream> send_closed_stream( 642 NewTestStream("send_closed.html")); 643 scoped_ptr<HttpStream> send_evicted_stream( 644 NewTestStream("send_evicted.html")); 645 scoped_ptr<HttpStream> send_rejected_stream( 646 NewTestStream("send_rejected.html")); 647 648 HttpRequestHeaders headers; 649 HttpResponseInfo response; 650 EXPECT_EQ(OK, closed_stream->SendRequest(headers, 651 &response, callback_.callback())); 652 EXPECT_EQ(OK, read_evicted_stream->SendRequest(headers, &response, 653 callback_.callback())); 654 EXPECT_EQ(OK, read_rejected_stream->SendRequest(headers, &response, 655 callback_.callback())); 656 TestCompletionCallback send_closed_callback; 657 EXPECT_EQ(ERR_IO_PENDING, 658 send_closed_stream->SendRequest(headers, &response, 659 send_closed_callback.callback())); 660 TestCompletionCallback send_evicted_callback; 661 EXPECT_EQ(ERR_IO_PENDING, 662 send_evicted_stream->SendRequest(headers, &response, 663 send_evicted_callback.callback())); 664 665 TestCompletionCallback read_evicted_callback; 666 EXPECT_EQ(ERR_IO_PENDING, 667 read_evicted_stream->ReadResponseHeaders( 668 read_evicted_callback.callback())); 669 670 EXPECT_EQ(OK, closed_stream->ReadResponseHeaders(callback_.callback())); 671 ExpectResponse("ok.html", closed_stream, false); 672 closed_stream->Close(true); 673 674 EXPECT_EQ(ERR_PIPELINE_EVICTION, read_evicted_callback.WaitForResult()); 675 read_evicted_stream->Close(true); 676 677 EXPECT_EQ(ERR_PIPELINE_EVICTION, 678 read_rejected_stream->ReadResponseHeaders(callback_.callback())); 679 read_rejected_stream->Close(true); 680 681 data_->RunFor(1); 682 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, send_closed_callback.WaitForResult()); 683 send_closed_stream->Close(true); 684 685 EXPECT_EQ(ERR_PIPELINE_EVICTION, send_evicted_callback.WaitForResult()); 686 send_evicted_stream->Close(true); 687 688 EXPECT_EQ(ERR_PIPELINE_EVICTION, 689 send_rejected_stream->SendRequest(headers, &response, 690 callback_.callback())); 691 send_rejected_stream->Close(true); 692 } 693 694 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSending) { 695 MockWrite writes[] = { 696 MockWrite(ASYNC, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), 697 }; 698 Initialize(NULL, 0, writes, arraysize(writes)); 699 700 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); 701 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 702 703 HttpRequestHeaders headers; 704 HttpResponseInfo response; 705 TestCompletionCallback aborted_callback; 706 EXPECT_EQ(ERR_IO_PENDING, 707 aborted_stream->SendRequest(headers, &response, 708 aborted_callback.callback())); 709 TestCompletionCallback evicted_callback; 710 EXPECT_EQ(ERR_IO_PENDING, 711 evicted_stream->SendRequest(headers, &response, 712 evicted_callback.callback())); 713 714 aborted_stream->Close(true); 715 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 716 evicted_stream->Close(true); 717 EXPECT_FALSE(aborted_callback.have_result()); 718 } 719 720 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendingSecondRequest) { 721 MockWrite writes[] = { 722 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 723 MockWrite(ASYNC, 1, "GET /aborts.html HTTP/1.1\r\n\r\n"), 724 }; 725 Initialize(NULL, 0, writes, arraysize(writes)); 726 727 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 728 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); 729 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 730 731 HttpRequestHeaders headers; 732 HttpResponseInfo response; 733 TestCompletionCallback ok_callback; 734 EXPECT_EQ(ERR_IO_PENDING, ok_stream->SendRequest(headers, &response, 735 ok_callback.callback())); 736 TestCompletionCallback aborted_callback; 737 EXPECT_EQ(ERR_IO_PENDING, 738 aborted_stream->SendRequest(headers, &response, 739 aborted_callback.callback())); 740 TestCompletionCallback evicted_callback; 741 EXPECT_EQ(ERR_IO_PENDING, 742 evicted_stream->SendRequest(headers, &response, 743 evicted_callback.callback())); 744 745 data_->RunFor(1); 746 EXPECT_LE(OK, ok_callback.WaitForResult()); 747 base::MessageLoop::current()->RunUntilIdle(); 748 aborted_stream->Close(true); 749 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 750 evicted_stream->Close(true); 751 EXPECT_FALSE(aborted_callback.have_result()); 752 ok_stream->Close(true); 753 } 754 755 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileReadingHeaders) { 756 MockWrite writes[] = { 757 MockWrite(SYNCHRONOUS, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), 758 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), 759 }; 760 MockRead reads[] = { 761 MockRead(ASYNC, ERR_FAILED, 2), 762 }; 763 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 764 765 scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); 766 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 767 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); 768 769 HttpRequestHeaders headers; 770 HttpResponseInfo response; 771 EXPECT_EQ(OK, 772 aborted_stream->SendRequest(headers, &response, 773 callback_.callback())); 774 EXPECT_EQ(OK, 775 evicted_stream->SendRequest(headers, &response, 776 callback_.callback())); 777 778 EXPECT_EQ(ERR_IO_PENDING, 779 aborted_stream->ReadResponseHeaders(callback_.callback())); 780 TestCompletionCallback evicted_callback; 781 EXPECT_EQ(ERR_IO_PENDING, 782 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); 783 784 aborted_stream->Close(true); 785 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 786 evicted_stream->Close(true); 787 788 EXPECT_EQ(ERR_PIPELINE_EVICTION, 789 rejected_stream->SendRequest(headers, &response, 790 callback_.callback())); 791 rejected_stream->Close(true); 792 } 793 794 TEST_F(HttpPipelinedConnectionImplTest, PendingResponseAbandoned) { 795 MockWrite writes[] = { 796 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 797 MockWrite(SYNCHRONOUS, 1, "GET /abandoned.html HTTP/1.1\r\n\r\n"), 798 MockWrite(SYNCHRONOUS, 2, "GET /evicted.html HTTP/1.1\r\n\r\n"), 799 }; 800 MockRead reads[] = { 801 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), 802 MockRead(SYNCHRONOUS, 4, "Content-Length: 7\r\n\r\n"), 803 MockRead(SYNCHRONOUS, 5, "ok.html"), 804 }; 805 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 806 807 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 808 scoped_ptr<HttpStream> abandoned_stream(NewTestStream("abandoned.html")); 809 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 810 811 HttpRequestHeaders headers; 812 HttpResponseInfo response; 813 EXPECT_EQ(OK, ok_stream->SendRequest(headers, &response, 814 callback_.callback())); 815 EXPECT_EQ(OK, abandoned_stream->SendRequest(headers, &response, 816 callback_.callback())); 817 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, 818 callback_.callback())); 819 820 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); 821 TestCompletionCallback abandoned_callback; 822 EXPECT_EQ(ERR_IO_PENDING, abandoned_stream->ReadResponseHeaders( 823 abandoned_callback.callback())); 824 TestCompletionCallback evicted_callback; 825 EXPECT_EQ(ERR_IO_PENDING, 826 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); 827 828 abandoned_stream->Close(false); 829 830 ExpectResponse("ok.html", ok_stream, false); 831 ok_stream->Close(false); 832 833 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 834 evicted_stream->Close(true); 835 EXPECT_FALSE(evicted_stream->IsConnectionReusable()); 836 } 837 838 TEST_F(HttpPipelinedConnectionImplTest, DisconnectedAfterOneRequestRecovery) { 839 MockWrite writes[] = { 840 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 841 MockWrite(SYNCHRONOUS, 1, "GET /rejected.html HTTP/1.1\r\n\r\n"), 842 MockWrite(ASYNC, ERR_SOCKET_NOT_CONNECTED, 5), 843 MockWrite(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 7), 844 }; 845 MockRead reads[] = { 846 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 847 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), 848 MockRead(SYNCHRONOUS, 4, "ok.html"), 849 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 6), 850 }; 851 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 852 853 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 854 scoped_ptr<HttpStream> rejected_read_stream(NewTestStream("rejected.html")); 855 scoped_ptr<HttpStream> evicted_send_stream(NewTestStream("evicted.html")); 856 scoped_ptr<HttpStream> rejected_send_stream(NewTestStream("rejected.html")); 857 858 HttpRequestHeaders headers; 859 HttpResponseInfo response; 860 EXPECT_EQ(OK, ok_stream->SendRequest(headers, 861 &response, callback_.callback())); 862 EXPECT_EQ(OK, rejected_read_stream->SendRequest(headers, &response, 863 callback_.callback())); 864 865 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); 866 ExpectResponse("ok.html", ok_stream, false); 867 ok_stream->Close(false); 868 869 TestCompletionCallback read_callback; 870 EXPECT_EQ(ERR_IO_PENDING, 871 evicted_send_stream->SendRequest(headers, &response, 872 read_callback.callback())); 873 data_->RunFor(1); 874 EXPECT_EQ(ERR_PIPELINE_EVICTION, read_callback.WaitForResult()); 875 876 EXPECT_EQ(ERR_PIPELINE_EVICTION, 877 rejected_read_stream->ReadResponseHeaders(callback_.callback())); 878 EXPECT_EQ(ERR_PIPELINE_EVICTION, 879 rejected_send_stream->SendRequest(headers, &response, 880 callback_.callback())); 881 882 rejected_read_stream->Close(true); 883 rejected_send_stream->Close(true); 884 } 885 886 TEST_F(HttpPipelinedConnectionImplTest, DisconnectedPendingReadRecovery) { 887 MockWrite writes[] = { 888 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 889 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), 890 }; 891 MockRead reads[] = { 892 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 893 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), 894 MockRead(SYNCHRONOUS, 4, "ok.html"), 895 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), 896 }; 897 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 898 899 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 900 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 901 902 HttpRequestHeaders headers; 903 HttpResponseInfo response; 904 EXPECT_EQ(OK, ok_stream->SendRequest(headers, 905 &response, callback_.callback())); 906 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, 907 callback_.callback())); 908 909 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); 910 ExpectResponse("ok.html", ok_stream, false); 911 912 TestCompletionCallback evicted_callback; 913 EXPECT_EQ(ERR_IO_PENDING, 914 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); 915 916 ok_stream->Close(false); 917 918 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 919 evicted_stream->Close(false); 920 } 921 922 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeNextReadLoop) { 923 MockWrite writes[] = { 924 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 925 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), 926 }; 927 MockRead reads[] = { 928 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 929 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), 930 MockRead(SYNCHRONOUS, 4, "ok.html"), 931 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), 932 }; 933 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 934 935 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 936 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 937 938 HttpRequestHeaders headers; 939 HttpResponseInfo response; 940 EXPECT_EQ(OK, ok_stream->SendRequest(headers, 941 &response, callback_.callback())); 942 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, 943 callback_.callback())); 944 945 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); 946 ExpectResponse("ok.html", ok_stream, false); 947 948 TestCompletionCallback evicted_callback; 949 EXPECT_EQ(ERR_IO_PENDING, 950 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); 951 952 ok_stream->Close(false); 953 evicted_stream->Close(false); 954 } 955 956 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeReadCallback) { 957 MockWrite writes[] = { 958 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 959 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), 960 }; 961 MockRead reads[] = { 962 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 963 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), 964 MockRead(SYNCHRONOUS, 4, "ok.html"), 965 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), 966 }; 967 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 968 969 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 970 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 971 972 HttpRequestHeaders headers; 973 HttpResponseInfo response; 974 EXPECT_EQ(OK, ok_stream->SendRequest(headers, 975 &response, callback_.callback())); 976 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, 977 callback_.callback())); 978 979 EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback())); 980 ExpectResponse("ok.html", ok_stream, false); 981 982 TestCompletionCallback evicted_callback; 983 EXPECT_EQ(ERR_IO_PENDING, 984 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); 985 986 ok_stream->Close(false); 987 988 // The posted tasks should be: 989 // 1. DoReadHeadersLoop, which will post: 990 // 2. InvokeUserCallback 991 SuddenCloseObserver observer(evicted_stream.get(), 2); 992 base::MessageLoop::current()->AddTaskObserver(&observer); 993 base::MessageLoop::current()->RunUntilIdle(); 994 EXPECT_FALSE(evicted_callback.have_result()); 995 } 996 997 class StreamDeleter { 998 public: 999 StreamDeleter(HttpStream* stream) 1000 : stream_(stream), 1001 callback_(base::Bind(&StreamDeleter::OnIOComplete, 1002 base::Unretained(this))) { 1003 } 1004 1005 ~StreamDeleter() { 1006 EXPECT_FALSE(stream_); 1007 } 1008 1009 const CompletionCallback& callback() { return callback_; } 1010 1011 private: 1012 void OnIOComplete(int result) { 1013 stream_->Close(true); 1014 stream_.reset(); 1015 } 1016 1017 scoped_ptr<HttpStream> stream_; 1018 CompletionCallback callback_; 1019 }; 1020 1021 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringSendCallback) { 1022 MockWrite writes[] = { 1023 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1024 }; 1025 Initialize(NULL, 0, writes, arraysize(writes)); 1026 1027 HttpStream* stream(NewTestStream("ok.html")); 1028 1029 StreamDeleter deleter(stream); 1030 HttpRequestHeaders headers; 1031 HttpResponseInfo response; 1032 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response, 1033 deleter.callback())); 1034 data_->RunFor(1); 1035 } 1036 1037 TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringReadCallback) { 1038 MockWrite writes[] = { 1039 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1040 }; 1041 MockRead reads[] = { 1042 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 1043 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), 1044 }; 1045 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1046 1047 HttpStream* stream(NewTestStream("ok.html")); 1048 1049 HttpRequestHeaders headers; 1050 HttpResponseInfo response; 1051 EXPECT_EQ(OK, stream->SendRequest(headers, 1052 &response, callback_.callback())); 1053 1054 StreamDeleter deleter(stream); 1055 EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(deleter.callback())); 1056 data_->RunFor(1); 1057 } 1058 1059 TEST_F(HttpPipelinedConnectionImplTest, 1060 CloseCalledDuringReadCallbackWithPendingRead) { 1061 MockWrite writes[] = { 1062 MockWrite(SYNCHRONOUS, 0, "GET /failed.html HTTP/1.1\r\n\r\n"), 1063 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), 1064 }; 1065 MockRead reads[] = { 1066 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 1067 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), 1068 }; 1069 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1070 1071 HttpStream* failed_stream(NewTestStream("failed.html")); 1072 HttpStream* evicted_stream(NewTestStream("evicted.html")); 1073 1074 HttpRequestHeaders headers; 1075 HttpResponseInfo response; 1076 EXPECT_EQ(OK, failed_stream->SendRequest(headers, &response, 1077 callback_.callback())); 1078 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response, 1079 callback_.callback())); 1080 1081 StreamDeleter failed_deleter(failed_stream); 1082 EXPECT_EQ(ERR_IO_PENDING, 1083 failed_stream->ReadResponseHeaders(failed_deleter.callback())); 1084 StreamDeleter evicted_deleter(evicted_stream); 1085 EXPECT_EQ(ERR_IO_PENDING, 1086 evicted_stream->ReadResponseHeaders(evicted_deleter.callback())); 1087 data_->RunFor(1); 1088 } 1089 1090 TEST_F(HttpPipelinedConnectionImplTest, CloseOtherDuringReadCallback) { 1091 MockWrite writes[] = { 1092 MockWrite(SYNCHRONOUS, 0, "GET /deleter.html HTTP/1.1\r\n\r\n"), 1093 MockWrite(SYNCHRONOUS, 1, "GET /deleted.html HTTP/1.1\r\n\r\n"), 1094 }; 1095 MockRead reads[] = { 1096 MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"), 1097 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), 1098 }; 1099 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1100 1101 scoped_ptr<HttpStream> deleter_stream(NewTestStream("deleter.html")); 1102 HttpStream* deleted_stream(NewTestStream("deleted.html")); 1103 1104 HttpRequestHeaders headers; 1105 HttpResponseInfo response; 1106 EXPECT_EQ(OK, deleter_stream->SendRequest(headers, 1107 &response, callback_.callback())); 1108 EXPECT_EQ(OK, deleted_stream->SendRequest(headers, 1109 &response, callback_.callback())); 1110 1111 StreamDeleter deleter(deleted_stream); 1112 EXPECT_EQ(ERR_IO_PENDING, 1113 deleter_stream->ReadResponseHeaders(deleter.callback())); 1114 EXPECT_EQ(ERR_IO_PENDING, 1115 deleted_stream->ReadResponseHeaders(callback_.callback())); 1116 data_->RunFor(1); 1117 } 1118 1119 TEST_F(HttpPipelinedConnectionImplTest, CloseBeforeSendCallbackRuns) { 1120 MockWrite writes[] = { 1121 MockWrite(ASYNC, 0, "GET /close.html HTTP/1.1\r\n\r\n"), 1122 MockWrite(ASYNC, 1, "GET /dummy.html HTTP/1.1\r\n\r\n"), 1123 }; 1124 Initialize(NULL, 0, writes, arraysize(writes)); 1125 1126 scoped_ptr<HttpStream> close_stream(NewTestStream("close.html")); 1127 scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html")); 1128 1129 scoped_ptr<TestCompletionCallback> close_callback( 1130 new TestCompletionCallback); 1131 HttpRequestHeaders headers; 1132 HttpResponseInfo response; 1133 EXPECT_EQ(ERR_IO_PENDING, 1134 close_stream->SendRequest(headers, 1135 &response, close_callback->callback())); 1136 1137 data_->RunFor(1); 1138 EXPECT_FALSE(close_callback->have_result()); 1139 1140 close_stream->Close(false); 1141 close_stream.reset(); 1142 close_callback.reset(); 1143 1144 base::MessageLoop::current()->RunUntilIdle(); 1145 } 1146 1147 TEST_F(HttpPipelinedConnectionImplTest, CloseBeforeReadCallbackRuns) { 1148 MockWrite writes[] = { 1149 MockWrite(SYNCHRONOUS, 0, "GET /close.html HTTP/1.1\r\n\r\n"), 1150 MockWrite(SYNCHRONOUS, 3, "GET /dummy.html HTTP/1.1\r\n\r\n"), 1151 }; 1152 MockRead reads[] = { 1153 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 1154 MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"), 1155 }; 1156 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1157 1158 scoped_ptr<HttpStream> close_stream(NewTestStream("close.html")); 1159 scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html")); 1160 1161 HttpRequestHeaders headers; 1162 HttpResponseInfo response; 1163 EXPECT_EQ(OK, close_stream->SendRequest(headers, 1164 &response, callback_.callback())); 1165 1166 scoped_ptr<TestCompletionCallback> close_callback( 1167 new TestCompletionCallback); 1168 EXPECT_EQ(ERR_IO_PENDING, 1169 close_stream->ReadResponseHeaders(close_callback->callback())); 1170 1171 data_->RunFor(1); 1172 EXPECT_FALSE(close_callback->have_result()); 1173 1174 close_stream->Close(false); 1175 close_stream.reset(); 1176 close_callback.reset(); 1177 1178 base::MessageLoop::current()->RunUntilIdle(); 1179 } 1180 1181 TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendQueued) { 1182 MockWrite writes[] = { 1183 MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1184 MockWrite(ASYNC, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), 1185 }; 1186 Initialize(NULL, 0, writes, arraysize(writes)); 1187 1188 scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); 1189 scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); 1190 1191 HttpRequestHeaders headers1; 1192 HttpResponseInfo response1; 1193 TestCompletionCallback callback1; 1194 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(headers1, &response1, 1195 callback1.callback())); 1196 1197 HttpRequestHeaders headers2; 1198 HttpResponseInfo response2; 1199 TestCompletionCallback callback2; 1200 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2, 1201 callback2.callback())); 1202 1203 stream2.reset(); 1204 stream1->Close(true); 1205 1206 EXPECT_FALSE(callback2.have_result()); 1207 } 1208 1209 TEST_F(HttpPipelinedConnectionImplTest, NoGapBetweenCloseAndEviction) { 1210 MockWrite writes[] = { 1211 MockWrite(SYNCHRONOUS, 0, "GET /close.html HTTP/1.1\r\n\r\n"), 1212 MockWrite(SYNCHRONOUS, 2, "GET /dummy.html HTTP/1.1\r\n\r\n"), 1213 }; 1214 MockRead reads[] = { 1215 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 1216 MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"), 1217 }; 1218 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1219 1220 scoped_ptr<HttpStream> close_stream(NewTestStream("close.html")); 1221 scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html")); 1222 1223 HttpRequestHeaders headers; 1224 HttpResponseInfo response; 1225 EXPECT_EQ(OK, close_stream->SendRequest(headers, &response, 1226 callback_.callback())); 1227 1228 TestCompletionCallback close_callback; 1229 EXPECT_EQ(ERR_IO_PENDING, 1230 close_stream->ReadResponseHeaders(close_callback.callback())); 1231 1232 EXPECT_EQ(OK, dummy_stream->SendRequest(headers, &response, 1233 callback_.callback())); 1234 1235 TestCompletionCallback dummy_callback; 1236 EXPECT_EQ(ERR_IO_PENDING, 1237 dummy_stream->ReadResponseHeaders(dummy_callback.callback())); 1238 1239 close_stream->Close(true); 1240 close_stream.reset(); 1241 1242 EXPECT_TRUE(dummy_callback.have_result()); 1243 EXPECT_EQ(ERR_PIPELINE_EVICTION, dummy_callback.WaitForResult()); 1244 dummy_stream->Close(true); 1245 dummy_stream.reset(); 1246 pipeline_.reset(); 1247 } 1248 1249 TEST_F(HttpPipelinedConnectionImplTest, RecoverFromDrainOnRedirect) { 1250 MockWrite writes[] = { 1251 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), 1252 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), 1253 }; 1254 MockRead reads[] = { 1255 MockRead(SYNCHRONOUS, 2, 1256 "HTTP/1.1 302 OK\r\n" 1257 "Content-Length: 8\r\n\r\n" 1258 "redirect"), 1259 MockRead(SYNCHRONOUS, 3, 1260 "HTTP/1.1 200 OK\r\n" 1261 "Content-Length: 7\r\n\r\n" 1262 "ok.html"), 1263 }; 1264 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1265 1266 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); 1267 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); 1268 1269 HttpRequestHeaders headers1; 1270 HttpResponseInfo response1; 1271 EXPECT_EQ(OK, stream1->SendRequest(headers1, 1272 &response1, callback_.callback())); 1273 HttpRequestHeaders headers2; 1274 HttpResponseInfo response2; 1275 EXPECT_EQ(OK, stream2->SendRequest(headers2, 1276 &response2, callback_.callback())); 1277 1278 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 1279 stream1.release()->Drain(NULL); 1280 1281 EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback())); 1282 ExpectResponse("ok.html", stream2, false); 1283 stream2->Close(false); 1284 } 1285 1286 TEST_F(HttpPipelinedConnectionImplTest, EvictAfterDrainOfUnknownSize) { 1287 MockWrite writes[] = { 1288 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), 1289 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), 1290 }; 1291 MockRead reads[] = { 1292 MockRead(SYNCHRONOUS, 2, 1293 "HTTP/1.1 302 OK\r\n\r\n" 1294 "redirect"), 1295 }; 1296 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1297 1298 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); 1299 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); 1300 1301 HttpRequestHeaders headers1; 1302 HttpResponseInfo response1; 1303 EXPECT_EQ(OK, stream1->SendRequest(headers1, 1304 &response1, callback_.callback())); 1305 HttpRequestHeaders headers2; 1306 HttpResponseInfo response2; 1307 EXPECT_EQ(OK, stream2->SendRequest(headers2, 1308 &response2, callback_.callback())); 1309 1310 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 1311 stream1.release()->Drain(NULL); 1312 1313 EXPECT_EQ(ERR_PIPELINE_EVICTION, 1314 stream2->ReadResponseHeaders(callback_.callback())); 1315 stream2->Close(false); 1316 } 1317 1318 TEST_F(HttpPipelinedConnectionImplTest, EvictAfterFailedDrain) { 1319 MockWrite writes[] = { 1320 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), 1321 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), 1322 }; 1323 MockRead reads[] = { 1324 MockRead(SYNCHRONOUS, 2, 1325 "HTTP/1.1 302 OK\r\n" 1326 "Content-Length: 8\r\n\r\n"), 1327 MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 3), 1328 }; 1329 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1330 1331 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); 1332 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); 1333 1334 HttpRequestHeaders headers1; 1335 HttpResponseInfo response1; 1336 EXPECT_EQ(OK, stream1->SendRequest(headers1, 1337 &response1, callback_.callback())); 1338 HttpRequestHeaders headers2; 1339 HttpResponseInfo response2; 1340 EXPECT_EQ(OK, stream2->SendRequest(headers2, 1341 &response2, callback_.callback())); 1342 1343 1344 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 1345 stream1.release()->Drain(NULL); 1346 1347 EXPECT_EQ(ERR_PIPELINE_EVICTION, 1348 stream2->ReadResponseHeaders(callback_.callback())); 1349 stream2->Close(false); 1350 } 1351 1352 TEST_F(HttpPipelinedConnectionImplTest, EvictIfDrainingChunkedEncoding) { 1353 MockWrite writes[] = { 1354 MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"), 1355 MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"), 1356 }; 1357 MockRead reads[] = { 1358 MockRead(SYNCHRONOUS, 2, 1359 "HTTP/1.1 302 OK\r\n" 1360 "Transfer-Encoding: chunked\r\n\r\n"), 1361 MockRead(SYNCHRONOUS, 3, 1362 "jibberish"), 1363 }; 1364 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1365 1366 scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html")); 1367 scoped_ptr<HttpStream> stream2(NewTestStream("ok.html")); 1368 1369 HttpRequestHeaders headers1; 1370 HttpResponseInfo response1; 1371 EXPECT_EQ(OK, stream1->SendRequest(headers1, 1372 &response1, callback_.callback())); 1373 HttpRequestHeaders headers2; 1374 HttpResponseInfo response2; 1375 EXPECT_EQ(OK, stream2->SendRequest(headers2, 1376 &response2, callback_.callback())); 1377 1378 1379 EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback())); 1380 stream1.release()->Drain(NULL); 1381 1382 EXPECT_EQ(ERR_PIPELINE_EVICTION, 1383 stream2->ReadResponseHeaders(callback_.callback())); 1384 stream2->Close(false); 1385 } 1386 1387 TEST_F(HttpPipelinedConnectionImplTest, EvictionDueToMissingContentLength) { 1388 MockWrite writes[] = { 1389 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1390 MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), 1391 MockWrite(SYNCHRONOUS, 2, "GET /rejected.html HTTP/1.1\r\n\r\n"), 1392 }; 1393 MockRead reads[] = { 1394 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"), 1395 MockRead(SYNCHRONOUS, 4, "ok.html"), 1396 MockRead(SYNCHRONOUS, OK, 5), 1397 }; 1398 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1399 1400 scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); 1401 scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); 1402 scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); 1403 1404 HttpRequestHeaders headers; 1405 HttpResponseInfo response; 1406 EXPECT_EQ(OK, ok_stream->SendRequest(headers, 1407 &response, callback_.callback())); 1408 EXPECT_EQ(OK, evicted_stream->SendRequest(headers, 1409 &response, callback_.callback())); 1410 EXPECT_EQ(OK, rejected_stream->SendRequest(headers, 1411 &response, callback_.callback())); 1412 1413 TestCompletionCallback ok_callback; 1414 EXPECT_EQ(ERR_IO_PENDING, 1415 ok_stream->ReadResponseHeaders(ok_callback.callback())); 1416 1417 TestCompletionCallback evicted_callback; 1418 EXPECT_EQ(ERR_IO_PENDING, 1419 evicted_stream->ReadResponseHeaders(evicted_callback.callback())); 1420 1421 data_->RunFor(1); 1422 EXPECT_LE(OK, ok_callback.WaitForResult()); 1423 data_->StopAfter(10); 1424 1425 ExpectResponse("ok.html", ok_stream, false); 1426 ok_stream->Close(false); 1427 1428 EXPECT_EQ(ERR_PIPELINE_EVICTION, 1429 rejected_stream->ReadResponseHeaders(callback_.callback())); 1430 rejected_stream->Close(true); 1431 EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); 1432 evicted_stream->Close(true); 1433 } 1434 1435 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnSocketError) { 1436 MockWrite writes[] = { 1437 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1438 }; 1439 MockRead reads[] = { 1440 MockRead(SYNCHRONOUS, ERR_FAILED, 1), 1441 }; 1442 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1443 1444 EXPECT_CALL(delegate_, 1445 OnPipelineFeedback( 1446 pipeline_.get(), 1447 HttpPipelinedConnection::PIPELINE_SOCKET_ERROR)) 1448 .Times(1); 1449 1450 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1451 HttpRequestHeaders headers; 1452 HttpResponseInfo response; 1453 EXPECT_EQ(OK, stream->SendRequest(headers, 1454 &response, callback_.callback())); 1455 EXPECT_EQ(ERR_FAILED, stream->ReadResponseHeaders(callback_.callback())); 1456 } 1457 1458 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnNoInternetConnection) { 1459 MockWrite writes[] = { 1460 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1461 }; 1462 MockRead reads[] = { 1463 MockRead(SYNCHRONOUS, ERR_INTERNET_DISCONNECTED, 1), 1464 }; 1465 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1466 1467 EXPECT_CALL(delegate_, OnPipelineFeedback(_, _)) 1468 .Times(0); 1469 1470 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1471 HttpRequestHeaders headers; 1472 HttpResponseInfo response; 1473 EXPECT_EQ(OK, stream->SendRequest(headers, 1474 &response, callback_.callback())); 1475 EXPECT_EQ(ERR_INTERNET_DISCONNECTED, 1476 stream->ReadResponseHeaders(callback_.callback())); 1477 } 1478 1479 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnHttp10) { 1480 MockWrite writes[] = { 1481 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1482 }; 1483 MockRead reads[] = { 1484 MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"), 1485 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n"), 1486 MockRead(SYNCHRONOUS, 3, "Connection: keep-alive\r\n\r\n"), 1487 MockRead(SYNCHRONOUS, 4, "ok.html"), 1488 }; 1489 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1490 1491 EXPECT_CALL(delegate_, 1492 OnPipelineFeedback(pipeline_.get(), 1493 HttpPipelinedConnection::OLD_HTTP_VERSION)) 1494 .Times(1); 1495 1496 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1497 TestSyncRequest(stream, "ok.html"); 1498 } 1499 1500 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnMustClose) { 1501 MockWrite writes[] = { 1502 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1503 }; 1504 MockRead reads[] = { 1505 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), 1506 MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n"), 1507 MockRead(SYNCHRONOUS, 3, "Connection: close\r\n\r\n"), 1508 MockRead(SYNCHRONOUS, 4, "ok.html"), 1509 }; 1510 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1511 1512 EXPECT_CALL(delegate_, 1513 OnPipelineFeedback( 1514 pipeline_.get(), 1515 HttpPipelinedConnection::MUST_CLOSE_CONNECTION)) 1516 .Times(1); 1517 1518 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1519 TestSyncRequest(stream, "ok.html"); 1520 } 1521 1522 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnNoContentLength) { 1523 MockWrite writes[] = { 1524 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1525 }; 1526 MockRead reads[] = { 1527 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), 1528 MockRead(SYNCHRONOUS, 2, "ok.html"), 1529 }; 1530 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1531 1532 EXPECT_CALL(delegate_, 1533 OnPipelineFeedback( 1534 pipeline_.get(), 1535 HttpPipelinedConnection::MUST_CLOSE_CONNECTION)) 1536 .Times(1); 1537 1538 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1539 TestSyncRequest(stream, "ok.html"); 1540 } 1541 1542 TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnAuthenticationRequired) { 1543 MockWrite writes[] = { 1544 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1545 }; 1546 MockRead reads[] = { 1547 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Unauthorized\r\n"), 1548 MockRead(SYNCHRONOUS, 2, "WWW-Authenticate: NTLM\r\n"), 1549 MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"), 1550 MockRead(SYNCHRONOUS, 4, "ok.html"), 1551 }; 1552 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1553 1554 EXPECT_CALL(delegate_, 1555 OnPipelineFeedback( 1556 pipeline_.get(), 1557 HttpPipelinedConnection::AUTHENTICATION_REQUIRED)) 1558 .Times(1); 1559 1560 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1561 TestSyncRequest(stream, "ok.html"); 1562 } 1563 1564 TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacity) { 1565 MockWrite writes[] = { 1566 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1567 }; 1568 Initialize(NULL, 0, writes, arraysize(writes)); 1569 1570 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); 1571 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1572 1573 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); 1574 HttpRequestHeaders headers; 1575 HttpResponseInfo response; 1576 EXPECT_EQ(OK, stream->SendRequest(headers, 1577 &response, callback_.callback())); 1578 1579 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); 1580 base::MessageLoop::current()->RunUntilIdle(); 1581 1582 stream->Close(false); 1583 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); 1584 stream.reset(NULL); 1585 } 1586 1587 TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacityWithoutSend) { 1588 MockWrite writes[] = { 1589 MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), 1590 }; 1591 Initialize(NULL, 0, writes, arraysize(writes)); 1592 1593 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); 1594 scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); 1595 1596 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); 1597 base::MessageLoop::current()->RunUntilIdle(); 1598 1599 stream->Close(false); 1600 EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); 1601 stream.reset(NULL); 1602 } 1603 1604 } // anonymous namespace 1605 1606 } // namespace net 1607