Index: net/http/http_pipelined_connection_impl_unittest.cc |
diff --git a/net/http/http_pipelined_connection_impl_unittest.cc b/net/http/http_pipelined_connection_impl_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..420d8dc401ba8096c78082ac6590c8259cbc24cc |
--- /dev/null |
+++ b/net/http/http_pipelined_connection_impl_unittest.cc |
@@ -0,0 +1,1067 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/http/http_pipelined_connection_impl.h" |
+ |
+#include <string> |
+ |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_vector.h" |
+#include "net/base/io_buffer.h" |
+#include "net/base/net_errors.h" |
+#include "net/base/request_priority.h" |
+#include "net/http/http_pipelined_stream.h" |
+#include "net/socket/client_socket_handle.h" |
+#include "net/socket/client_socket_pool_histograms.h" |
+#include "net/socket/socket_test_util.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using testing::NiceMock; |
+using testing::StrEq; |
+ |
+namespace net { |
+ |
+class DummySocketParams : public base::RefCounted<DummySocketParams> { |
+ private: |
+ friend class base::RefCounted<DummySocketParams>; |
+}; |
+ |
+REGISTER_SOCKET_PARAMS_FOR_POOL(MockTransportClientSocketPool, |
+ DummySocketParams); |
+ |
+class MockPipelineDelegate : public HttpPipelinedConnectionImpl::Delegate { |
+ public: |
+ MOCK_METHOD1(OnPipelineHasCapacity, void(HttpPipelinedConnection* pipeline)); |
+}; |
+ |
+class SuddenCloseObserver : public MessageLoop::TaskObserver { |
+ public: |
+ SuddenCloseObserver(HttpStream* stream, int close_before_task) |
+ : stream_(stream), |
+ close_before_task_(close_before_task), |
+ current_task_(0) { } |
+ |
+ virtual void WillProcessTask(base::TimeTicks) OVERRIDE { |
+ ++current_task_; |
+ if (current_task_ == close_before_task_) { |
+ stream_->Close(false); |
+ MessageLoop::current()->RemoveTaskObserver(this); |
+ } |
+ } |
+ |
+ virtual void DidProcessTask(base::TimeTicks) OVERRIDE { } |
+ |
+ private: |
+ HttpStream* stream_; |
+ int close_before_task_; |
+ int current_task_; |
+}; |
+ |
+class HttpPipelinedConnectionImplTest : public testing::Test { |
+ public: |
+ HttpPipelinedConnectionImplTest() |
+ : histograms_("a"), |
+ pool_(1, 1, &histograms_, &factory_) { |
+ } |
+ |
+ void TearDown() { |
+ MessageLoop::current()->RunAllPending(); |
+ } |
+ |
+ void Initialize(MockRead* reads, size_t reads_count, |
+ MockWrite* writes, size_t writes_count) { |
+ data_ = new DeterministicSocketData(reads, reads_count, |
+ writes, writes_count); |
+ data_->set_connect_data(MockConnect(false, 0)); |
+ if (reads_count || writes_count) { |
+ data_->StopAfter(reads_count + writes_count); |
+ } |
+ factory_.AddSocketDataProvider(data_.get()); |
+ scoped_refptr<DummySocketParams> params; |
+ ClientSocketHandle* connection = new ClientSocketHandle; |
+ connection->Init("a", params, MEDIUM, NULL, &pool_, BoundNetLog()); |
+ pipeline_.reset(new HttpPipelinedConnectionImpl(connection, &delegate_, |
+ ssl_config_, proxy_info_, |
+ BoundNetLog(), false)); |
+ } |
+ |
+ HttpRequestInfo* GetRequestInfo(const std::string& filename) { |
+ HttpRequestInfo* request_info = new HttpRequestInfo; |
+ request_info->url = GURL("http://localhost/" + filename); |
+ request_info->method = "GET"; |
+ request_info_vector_.push_back(request_info); |
+ return request_info; |
+ } |
+ |
+ HttpStream* NewTestStream(const std::string& filename) { |
+ HttpStream* stream = pipeline_->CreateNewStream(); |
+ HttpRequestInfo* request_info = GetRequestInfo(filename); |
+ int rv = stream->InitializeStream(request_info, BoundNetLog(), NULL); |
+ DCHECK_EQ(OK, rv); |
+ return stream; |
+ } |
+ |
+ void ExpectResponse(const std::string& expected, |
+ scoped_ptr<HttpStream>& stream, bool async) { |
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); |
+ |
+ if (async) { |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream->ReadResponseBody(buffer.get(), expected.size(), |
+ &callback_)); |
+ data_->RunFor(1); |
+ EXPECT_EQ(static_cast<int>(expected.size()), callback_.WaitForResult()); |
+ } else { |
+ EXPECT_EQ(static_cast<int>(expected.size()), |
+ stream->ReadResponseBody(buffer.get(), expected.size(), |
+ &callback_)); |
+ } |
+ std::string actual(buffer->data(), expected.size()); |
+ EXPECT_THAT(actual, StrEq(expected)); |
+ } |
+ |
+ void TestSyncRequest(scoped_ptr<HttpStream>& stream, |
+ const std::string& filename) { |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, stream->ReadResponseHeaders(&callback_)); |
+ ExpectResponse(filename, stream, false); |
+ |
+ stream->Close(false); |
+ } |
+ |
+ DeterministicMockClientSocketFactory factory_; |
+ ClientSocketPoolHistograms histograms_; |
+ MockTransportClientSocketPool pool_; |
+ scoped_refptr<DeterministicSocketData> data_; |
+ |
+ SSLConfig ssl_config_; |
+ ProxyInfo proxy_info_; |
+ NiceMock<MockPipelineDelegate> delegate_; |
+ TestOldCompletionCallback callback_; |
+ scoped_ptr<HttpPipelinedConnectionImpl> pipeline_; |
+ ScopedVector<HttpRequestInfo> request_info_vector_; |
+}; |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, PipelineNotUsed) { |
+ Initialize(NULL, 0, NULL, 0); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, StreamNotUsed) { |
+ Initialize(NULL, 0, NULL, 0); |
+ |
+ scoped_ptr<HttpStream> stream(pipeline_->CreateNewStream()); |
+ |
+ stream->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, StreamBoundButNotUsed) { |
+ Initialize(NULL, 0, NULL, 0); |
+ |
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); |
+ |
+ stream->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, SyncSingleRequest) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 3, "ok.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); |
+ TestSyncRequest(stream, "ok.html"); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, AsyncSingleRequest) { |
+ MockWrite writes[] = { |
+ MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(true, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(true, 3, "ok.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream->SendRequest(headers, NULL, &response, &callback_)); |
+ data_->RunFor(1); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(&callback_)); |
+ data_->RunFor(2); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ ExpectResponse("ok.html", stream, true); |
+ |
+ stream->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, LockStepAsyncRequests) { |
+ MockWrite writes[] = { |
+ MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(true, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(true, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 3, "Content-Length: 7\r\n\r\n"), |
+ MockRead(true, 4, "ok.html"), |
+ MockRead(true, 5, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 6, "Content-Length: 7\r\n\r\n"), |
+ MockRead(true, 7, "ko.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); |
+ |
+ HttpRequestHeaders headers1; |
+ HttpResponseInfo response1; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream1->SendRequest(headers1, NULL, &response1, &callback_)); |
+ |
+ HttpRequestHeaders headers2; |
+ HttpResponseInfo response2; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream2->SendRequest(headers2, NULL, &response2, &callback_)); |
+ |
+ data_->RunFor(1); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ data_->RunFor(1); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, stream1->ReadResponseHeaders(&callback_)); |
+ EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(&callback_)); |
+ |
+ data_->RunFor(2); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ ExpectResponse("ok.html", stream1, true); |
+ |
+ stream1->Close(false); |
+ |
+ data_->RunFor(2); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ ExpectResponse("ko.html", stream2, true); |
+ |
+ stream2->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, TwoResponsesInOnePacket) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, |
+ "HTTP/1.1 200 OK\r\n" |
+ "Content-Length: 7\r\n\r\n" |
+ "ok.html" |
+ "HTTP/1.1 200 OK\r\n" |
+ "Content-Length: 7\r\n\r\n" |
+ "ko.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); |
+ |
+ HttpRequestHeaders headers1; |
+ HttpResponseInfo response1; |
+ EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); |
+ HttpRequestHeaders headers2; |
+ HttpResponseInfo response2; |
+ EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); |
+ |
+ EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", stream1, false); |
+ stream1->Close(false); |
+ |
+ EXPECT_EQ(OK, stream2->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ko.html", stream2, false); |
+ stream2->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, SendOrderSwapped) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 4, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 3, "ko.html"), |
+ MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 6, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 7, "ok.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); |
+ |
+ TestSyncRequest(stream2, "ko.html"); |
+ TestSyncRequest(stream1, "ok.html"); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, ReadOrderSwapped) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 3, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 6, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 7, "ko.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); |
+ |
+ HttpRequestHeaders headers1; |
+ HttpResponseInfo response1; |
+ EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); |
+ |
+ HttpRequestHeaders headers2; |
+ HttpResponseInfo response2; |
+ EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(&callback_)); |
+ |
+ EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", stream1, false); |
+ |
+ stream1->Close(false); |
+ |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ ExpectResponse("ko.html", stream2, false); |
+ |
+ stream2->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, SendWhileReading) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 6, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 7, "ko.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); |
+ |
+ HttpRequestHeaders headers1; |
+ HttpResponseInfo response1; |
+ EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); |
+ EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); |
+ |
+ HttpRequestHeaders headers2; |
+ HttpResponseInfo response2; |
+ EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_)); |
+ |
+ ExpectResponse("ok.html", stream1, false); |
+ stream1->Close(false); |
+ |
+ EXPECT_EQ(OK, stream2->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ko.html", stream2, false); |
+ stream2->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, AsyncSendWhileAsyncReadBlocked) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(true, 3, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(true, 4, "ok.html"), |
+ MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 6, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 7, "ko.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream1(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> stream2(NewTestStream("ko.html")); |
+ |
+ HttpRequestHeaders headers1; |
+ HttpResponseInfo response1; |
+ EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_)); |
+ EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_)); |
+ TestOldCompletionCallback callback1; |
+ std::string expected = "ok.html"; |
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream1->ReadResponseBody(buffer.get(), expected.size(), |
+ &callback1)); |
+ |
+ HttpRequestHeaders headers2; |
+ HttpResponseInfo response2; |
+ TestOldCompletionCallback callback2; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream2->SendRequest(headers2, NULL, &response2, &callback2)); |
+ |
+ data_->RunFor(1); |
+ EXPECT_LE(OK, callback2.WaitForResult()); |
+ EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(&callback2)); |
+ |
+ data_->RunFor(1); |
+ EXPECT_EQ(static_cast<int>(expected.size()), callback1.WaitForResult()); |
+ std::string actual(buffer->data(), expected.size()); |
+ EXPECT_THAT(actual, StrEq(expected)); |
+ stream1->Close(false); |
+ |
+ data_->StopAfter(8); |
+ EXPECT_LE(OK, callback2.WaitForResult()); |
+ ExpectResponse("ko.html", stream2, false); |
+ stream2->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, UnusedStreamAllowsLaterUse) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 3, "ok.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> unused_stream(NewTestStream("unused.html")); |
+ unused_stream->Close(false); |
+ |
+ scoped_ptr<HttpStream> later_stream(NewTestStream("ok.html")); |
+ TestSyncRequest(later_stream, "ok.html"); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, UnsentStreamAllowsLaterUse) { |
+ MockWrite writes[] = { |
+ MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 4, "GET /ko.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(true, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 2, "Content-Length: 7\r\n\r\n"), |
+ MockRead(true, 3, "ok.html"), |
+ MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 6, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 7, "ko.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ stream->SendRequest(headers, NULL, &response, &callback_)); |
+ |
+ scoped_ptr<HttpStream> unsent_stream(NewTestStream("unsent.html")); |
+ HttpRequestHeaders unsent_headers; |
+ HttpResponseInfo unsent_response; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ unsent_stream->SendRequest(unsent_headers, NULL, &unsent_response, |
+ &callback_)); |
+ unsent_stream->Close(false); |
+ |
+ data_->RunFor(1); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(&callback_)); |
+ data_->RunFor(2); |
+ EXPECT_LE(OK, callback_.WaitForResult()); |
+ |
+ ExpectResponse("ok.html", stream, true); |
+ |
+ stream->Close(false); |
+ |
+ data_->StopAfter(8); |
+ scoped_ptr<HttpStream> later_stream(NewTestStream("ko.html")); |
+ TestSyncRequest(later_stream, "ko.html"); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, FailedSend) { |
+ MockWrite writes[] = { |
+ MockWrite(true, ERR_FAILED), |
+ }; |
+ Initialize(NULL, 0, writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> failed_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ scoped_ptr<HttpStream> closed_stream(NewTestStream("closed.html")); |
+ scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ TestOldCompletionCallback failed_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ failed_stream->SendRequest(headers, NULL, &response, |
+ &failed_callback)); |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->SendRequest(headers, NULL, &response, |
+ &evicted_callback)); |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ closed_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ closed_stream->Close(false); |
+ |
+ data_->RunFor(1); |
+ EXPECT_EQ(ERR_FAILED, failed_callback.WaitForResult()); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, |
+ rejected_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ |
+ failed_stream->Close(true); |
+ evicted_stream->Close(true); |
+ rejected_stream->Close(true); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, ConnectionSuddenlyClosedAfterResponse) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /read_evicted.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 2, "GET /read_rejected.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(true, ERR_SOCKET_NOT_CONNECTED, 5), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 3, "HTTP/1.1 200 OK\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> closed_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> read_evicted_stream( |
+ NewTestStream("read_evicted.html")); |
+ scoped_ptr<HttpStream> read_rejected_stream( |
+ NewTestStream("read_rejected.html")); |
+ scoped_ptr<HttpStream> send_closed_stream( |
+ NewTestStream("send_closed.html")); |
+ scoped_ptr<HttpStream> send_evicted_stream( |
+ NewTestStream("send_evicted.html")); |
+ scoped_ptr<HttpStream> send_rejected_stream( |
+ NewTestStream("send_rejected.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, closed_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ EXPECT_EQ(OK, read_evicted_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ EXPECT_EQ(OK, read_rejected_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ TestOldCompletionCallback send_closed_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ send_closed_stream->SendRequest(headers, NULL, &response, |
+ &send_closed_callback)); |
+ TestOldCompletionCallback send_evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ send_evicted_stream->SendRequest(headers, NULL, &response, |
+ &send_evicted_callback)); |
+ |
+ TestOldCompletionCallback read_evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ read_evicted_stream->ReadResponseHeaders(&read_evicted_callback)); |
+ |
+ EXPECT_EQ(OK, closed_stream->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", closed_stream, false); |
+ closed_stream->Close(true); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, read_evicted_callback.WaitForResult()); |
+ read_evicted_stream->Close(true); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, |
+ read_rejected_stream->ReadResponseHeaders(&callback_)); |
+ read_rejected_stream->Close(true); |
+ |
+ data_->RunFor(1); |
+ EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, send_closed_callback.WaitForResult()); |
+ send_closed_stream->Close(true); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, send_evicted_callback.WaitForResult()); |
+ send_evicted_stream->Close(true); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, |
+ send_rejected_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ send_rejected_stream->Close(true); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSending) { |
+ MockWrite writes[] = { |
+ MockWrite(true, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ Initialize(NULL, 0, writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ TestOldCompletionCallback aborted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ aborted_stream->SendRequest(headers, NULL, &response, |
+ &aborted_callback)); |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->SendRequest(headers, NULL, &response, |
+ &evicted_callback)); |
+ |
+ aborted_stream->Close(true); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); |
+ evicted_stream->Close(true); |
+ EXPECT_FALSE(aborted_callback.have_result()); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendingSecondRequest) { |
+ MockWrite writes[] = { |
+ MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(true, 1, "GET /aborts.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ Initialize(NULL, 0, writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ TestOldCompletionCallback ok_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ ok_stream->SendRequest(headers, NULL, &response, |
+ &ok_callback)); |
+ TestOldCompletionCallback aborted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ aborted_stream->SendRequest(headers, NULL, &response, |
+ &aborted_callback)); |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->SendRequest(headers, NULL, &response, |
+ &evicted_callback)); |
+ |
+ data_->RunFor(1); |
+ EXPECT_LE(OK, ok_callback.WaitForResult()); |
+ MessageLoop::current()->RunAllPending(); |
+ aborted_stream->Close(true); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); |
+ evicted_stream->Close(true); |
+ EXPECT_FALSE(aborted_callback.have_result()); |
+ ok_stream->Close(true); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, AbortWhileReadingHeaders) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(true, ERR_FAILED, 2), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, aborted_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ EXPECT_EQ(OK, evicted_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, aborted_stream->ReadResponseHeaders(&callback_)); |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->ReadResponseHeaders(&evicted_callback)); |
+ |
+ aborted_stream->Close(true); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); |
+ evicted_stream->Close(true); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, |
+ rejected_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ rejected_stream->Close(true); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, PendingResponseAbandoned) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /abandoned.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 2, "GET /evicted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 3, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 4, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 5, "ok.html"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> abandoned_stream(NewTestStream("abandoned.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, ok_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, abandoned_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ EXPECT_EQ(OK, evicted_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ |
+ EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(&callback_)); |
+ TestOldCompletionCallback abandoned_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ abandoned_stream->ReadResponseHeaders(&abandoned_callback)); |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->ReadResponseHeaders(&evicted_callback)); |
+ |
+ abandoned_stream->Close(false); |
+ |
+ ExpectResponse("ok.html", ok_stream, false); |
+ ok_stream->Close(false); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); |
+ evicted_stream->Close(true); |
+ EXPECT_FALSE(evicted_stream->IsConnectionReusable()); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, DisconnectedAfterOneRequestRecovery) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /rejected.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(true, ERR_SOCKET_NOT_CONNECTED, 5), |
+ MockWrite(false, ERR_SOCKET_NOT_CONNECTED, 7), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 3, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ MockRead(false, ERR_SOCKET_NOT_CONNECTED, 6), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> rejected_read_stream(NewTestStream("rejected.html")); |
+ scoped_ptr<HttpStream> evicted_send_stream(NewTestStream("evicted.html")); |
+ scoped_ptr<HttpStream> rejected_send_stream(NewTestStream("rejected.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, ok_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, rejected_read_stream->SendRequest( |
+ headers, NULL, &response, &callback_)); |
+ |
+ EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", ok_stream, false); |
+ ok_stream->Close(false); |
+ |
+ TestOldCompletionCallback read_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_send_stream->SendRequest(headers, NULL, &response, |
+ &read_callback)); |
+ data_->RunFor(1); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, read_callback.WaitForResult()); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, |
+ rejected_read_stream->ReadResponseHeaders(&callback_)); |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, |
+ rejected_send_stream->SendRequest(headers, NULL, &response, |
+ &callback_)); |
+ |
+ rejected_read_stream->Close(true); |
+ rejected_send_stream->Close(true); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, DisconnectedPendingReadRecovery) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 3, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ MockRead(false, ERR_SOCKET_NOT_CONNECTED, 5), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, ok_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, evicted_stream->SendRequest( |
+ headers, NULL, &response, &callback_)); |
+ |
+ EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", ok_stream, false); |
+ |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->ReadResponseHeaders(&evicted_callback)); |
+ |
+ ok_stream->Close(false); |
+ |
+ EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult()); |
+ evicted_stream->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeNextReadLoop) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 3, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ MockRead(false, ERR_SOCKET_NOT_CONNECTED, 5), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, ok_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, evicted_stream->SendRequest( |
+ headers, NULL, &response, &callback_)); |
+ |
+ EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", ok_stream, false); |
+ |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->ReadResponseHeaders(&evicted_callback)); |
+ |
+ ok_stream->Close(false); |
+ evicted_stream->Close(false); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeReadCallback) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(false, 3, "Content-Length: 7\r\n\r\n"), |
+ MockRead(false, 4, "ok.html"), |
+ MockRead(false, ERR_SOCKET_NOT_CONNECTED, 5), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html")); |
+ scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, ok_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, evicted_stream->SendRequest( |
+ headers, NULL, &response, &callback_)); |
+ |
+ EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(&callback_)); |
+ ExpectResponse("ok.html", ok_stream, false); |
+ |
+ TestOldCompletionCallback evicted_callback; |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->ReadResponseHeaders(&evicted_callback)); |
+ |
+ ok_stream->Close(false); |
+ |
+ // The posted tasks should be: |
+ // 1. DoReadHeadersLoop, which will post: |
+ // 2. InvokeUserCallback |
+ SuddenCloseObserver observer(evicted_stream.get(), 2); |
+ MessageLoop::current()->AddTaskObserver(&observer); |
+ MessageLoop::current()->RunAllPending(); |
+ EXPECT_FALSE(evicted_callback.have_result()); |
+} |
+ |
+class StreamDeleter { |
+ public: |
+ StreamDeleter(HttpStream* stream) : |
+ stream_(stream), |
+ ALLOW_THIS_IN_INITIALIZER_LIST( |
+ callback_(this, &StreamDeleter::OnIOComplete)) { |
+ } |
+ |
+ OldCompletionCallbackImpl<StreamDeleter>* callback() { return &callback_; } |
+ |
+ private: |
+ void OnIOComplete(int result) { |
+ delete stream_; |
+ } |
+ |
+ HttpStream* stream_; |
+ OldCompletionCallbackImpl<StreamDeleter> callback_; |
+}; |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringSendCallback) { |
+ MockWrite writes[] = { |
+ MockWrite(true, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ Initialize(NULL, 0, writes, arraysize(writes)); |
+ |
+ HttpStream* stream(NewTestStream("ok.html")); |
+ |
+ StreamDeleter deleter(stream); |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, NULL, &response, |
+ deleter.callback())); |
+ data_->RunFor(1); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringReadCallback) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 2, "Content-Length: 7\r\n\r\n"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ HttpStream* stream(NewTestStream("ok.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, stream->SendRequest(headers, NULL, &response, &callback_)); |
+ |
+ StreamDeleter deleter(stream); |
+ EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(deleter.callback())); |
+ data_->RunFor(1); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, |
+ CloseCalledDuringReadCallbackWithPendingRead) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /failed.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 3, "Content-Length: 7\r\n\r\n"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ HttpStream* failed_stream(NewTestStream("failed.html")); |
+ HttpStream* evicted_stream(NewTestStream("evicted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, |
+ failed_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, |
+ evicted_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ |
+ StreamDeleter failed_deleter(failed_stream); |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ failed_stream->ReadResponseHeaders(failed_deleter.callback())); |
+ StreamDeleter evicted_deleter(evicted_stream); |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ evicted_stream->ReadResponseHeaders(evicted_deleter.callback())); |
+ data_->RunFor(1); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, CloseOtherDuringReadCallback) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /deleter.html HTTP/1.1\r\n\r\n"), |
+ MockWrite(false, 1, "GET /deleted.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ MockRead reads[] = { |
+ MockRead(false, 2, "HTTP/1.1 200 OK\r\n"), |
+ MockRead(true, 3, "Content-Length: 7\r\n\r\n"), |
+ }; |
+ Initialize(reads, arraysize(reads), writes, arraysize(writes)); |
+ |
+ scoped_ptr<HttpStream> deleter_stream(NewTestStream("deleter.html")); |
+ HttpStream* deleted_stream(NewTestStream("deleted.html")); |
+ |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, |
+ deleter_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ EXPECT_EQ(OK, |
+ deleted_stream->SendRequest(headers, NULL, &response, &callback_)); |
+ |
+ StreamDeleter deleter(deleted_stream); |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ deleter_stream->ReadResponseHeaders(deleter.callback())); |
+ EXPECT_EQ(ERR_IO_PENDING, deleted_stream->ReadResponseHeaders(&callback_)); |
+ data_->RunFor(1); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacity) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ Initialize(NULL, 0, writes, arraysize(writes)); |
+ |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); |
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); |
+ |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); |
+ HttpRequestHeaders headers; |
+ HttpResponseInfo response; |
+ EXPECT_EQ(OK, stream->SendRequest(headers, NULL, &response, &callback_)); |
+ |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); |
+ MessageLoop::current()->RunAllPending(); |
+ |
+ stream->Close(false); |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); |
+ stream.reset(NULL); |
+} |
+ |
+TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacityWithoutSend) { |
+ MockWrite writes[] = { |
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"), |
+ }; |
+ Initialize(NULL, 0, writes, arraysize(writes)); |
+ |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0); |
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html")); |
+ |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); |
+ MessageLoop::current()->RunAllPending(); |
+ |
+ stream->Close(false); |
+ EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1); |
+ stream.reset(NULL); |
+} |
+ |
+} // namespace net |