Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(414)

Unified Diff: net/http/http_pipelined_connection_impl_unittest.cc

Issue 7289006: Basic HTTP pipelining support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added unit tests Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..d73ce77e1fd961512a891ba8619a356fdfc73b26
--- /dev/null
+++ b/net/http/http_pipelined_connection_impl_unittest.cc
@@ -0,0 +1,740 @@
+// 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>
mmenke 2011/08/23 19:05:25 nit: Add blank link.
James Simonsen 2011/08/26 22:19:07 Done.
+#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::Ref;
+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 MockPipelineOwner : public HttpPipelinedConnectionImpl::Owner {
+ public:
+ MOCK_METHOD1(OnPipelineHasCapacity, void(HttpPipelinedConnection* pipeline));
+};
+
+class HttpPipelinedConnectionImplTest : public testing::Test {
+ public:
+ HttpPipelinedConnectionImplTest()
+ : histograms_("a"),
+ pool_(1, 1, &histograms_, &factory_) {
+ }
+
+ 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, &owner_,
+ 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<MockPipelineOwner> owner_;
+ TestCompletionCallback callback_;
+ scoped_ptr<HttpPipelinedConnectionImpl> pipeline_;
+ ScopedVector<HttpRequestInfo> request_info_vector_;
+};
+
+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, InitializeOrderSwapped) {
+ 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, SendOrderSwapped) {
mmenke 2011/08/23 19:05:25 How is this different from the previous test?
James Simonsen 2011/08/26 22:19:07 Hmm. It was different at one point, but I oversimp
+ 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"));
+
+ HttpRequestHeaders headers2;
+ HttpResponseInfo response2;
+ EXPECT_EQ(OK, stream2->SendRequest(headers2, NULL, &response2, &callback_));
+ EXPECT_EQ(OK, stream2->ReadResponseHeaders(&callback_));
+ ExpectResponse("ko.html", stream2, false);
+
+ stream2->Close(false);
+
+ HttpRequestHeaders headers1;
+ HttpResponseInfo response1;
+ EXPECT_EQ(OK, stream1->SendRequest(headers1, NULL, &response1, &callback_));
+ EXPECT_EQ(OK, stream1->ReadResponseHeaders(&callback_));
+ ExpectResponse("ok.html", stream1, false);
+
+ stream1->Close(false);
+}
+
+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_));
+ TestCompletionCallback 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;
+ TestCompletionCallback 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, PipelineNotUsed) {
mmenke 2011/08/23 19:05:25 nit: Might want to put this test as well as the n
James Simonsen 2011/08/26 22:19:07 Done.
+ MockWrite writes[] = {};
mmenke 2011/08/23 19:05:25 MSVC doesn't like 0-length arrays like this.
James Simonsen 2011/08/26 22:19:07 Lame. Fixed.
+ MockRead reads[] = {};
+ Initialize(reads, 0, writes, 0);
+}
+
+TEST_F(HttpPipelinedConnectionImplTest, StreamNotUsed) {
+ MockWrite writes[] = {};
+ MockRead reads[] = {};
+ Initialize(reads, 0, writes, 0);
+
+ scoped_ptr<HttpStream> stream(pipeline_->CreateNewStream());
+
+ stream->Close(false);
+}
+
+TEST_F(HttpPipelinedConnectionImplTest, StreamBoundButNotUsed) {
+ MockWrite writes[] = {};
+ MockRead reads[] = {};
+ Initialize(reads, 0, writes, 0);
+
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
+
+ stream->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),
+ };
+ MockRead reads[] = {};
+ Initialize(reads, 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;
+ TestCompletionCallback failed_callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ failed_stream->SendRequest(headers, NULL, &response,
+ &failed_callback));
+ TestCompletionCallback 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_));
+ TestCompletionCallback send_closed_callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ send_closed_stream->SendRequest(headers, NULL, &response,
+ &send_closed_callback));
+ TestCompletionCallback send_evicted_callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ send_evicted_stream->SendRequest(headers, NULL, &response,
+ &send_evicted_callback));
+
+ TestCompletionCallback read_evicted_callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ read_evicted_stream->ReadResponseHeaders(&read_evicted_callback));
+
+ EXPECT_EQ(OK, closed_stream->ReadResponseHeaders(&callback_));
+ std::string expected = "ok.html";
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size() + 10));
+ EXPECT_EQ(static_cast<int>(expected.size()),
+ closed_stream->ReadResponseBody(buffer.get(), expected.size() + 10,
+ &callback_));
+ std::string actual(buffer->data(), expected.size());
+ EXPECT_THAT(actual, StrEq(expected));
mmenke 2011/08/23 19:05:25 nit: Instead of the above lines, could just use:
James Simonsen 2011/08/26 22:19:07 Good eye. Fixed.
+ 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, 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_));
+ TestCompletionCallback 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) {
mmenke 2011/08/23 19:05:25 Out of general paranoia, should also have tests wh
James Simonsen 2011/08/26 22:19:07 Nice. Caught a bug too.
+ 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_));
+ TestCompletionCallback abandoned_callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ abandoned_stream->ReadResponseHeaders(&abandoned_callback));
+ TestCompletionCallback 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, OnPipelineHasCapacity) {
+ MockWrite writes[] = {
+ MockWrite(false, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
+ };
+ MockRead reads[] = {};
+ Initialize(reads, 0, writes, arraysize(writes));
+
+ scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
+
+ EXPECT_CALL(owner_, OnPipelineHasCapacity(pipeline_.get())).Times(1);
+ HttpRequestHeaders headers;
+ HttpResponseInfo response;
+ EXPECT_EQ(OK, stream->SendRequest(headers, NULL, &response, &callback_));
+ MessageLoop::current()->RunAllPending();
+
+ stream->Close(false);
+ EXPECT_CALL(owner_, OnPipelineHasCapacity(pipeline_.get())).Times(1);
+ stream.reset(NULL);
+ MessageLoop::current()->RunAllPending();
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698