diff options
Diffstat (limited to 'chromium/net/http/http_pipelined_network_transaction_unittest.cc')
-rw-r--r-- | chromium/net/http/http_pipelined_network_transaction_unittest.cc | 1035 |
1 files changed, 0 insertions, 1035 deletions
diff --git a/chromium/net/http/http_pipelined_network_transaction_unittest.cc b/chromium/net/http/http_pipelined_network_transaction_unittest.cc deleted file mode 100644 index 80b74fd554b..00000000000 --- a/chromium/net/http/http_pipelined_network_transaction_unittest.cc +++ /dev/null @@ -1,1035 +0,0 @@ -// Copyright (c) 2012 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 <string> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "net/base/address_list.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/base/request_priority.h" -#include "net/dns/host_cache.h" -#include "net/dns/mock_host_resolver.h" -#include "net/http/http_auth_handler_mock.h" -#include "net/http/http_network_session.h" -#include "net/http/http_network_transaction.h" -#include "net/http/http_request_info.h" -#include "net/http/http_server_properties_impl.h" -#include "net/proxy/proxy_config_service.h" -#include "net/proxy/proxy_service.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/client_socket_pool_histograms.h" -#include "net/socket/client_socket_pool_manager.h" -#include "net/socket/socket_test_util.h" -#include "net/ssl/ssl_config_service_defaults.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::StrEq; - -namespace net { - -namespace { - -class SimpleProxyConfigService : public ProxyConfigService { - public: - virtual void AddObserver(Observer* observer) OVERRIDE { - observer_ = observer; - } - - virtual void RemoveObserver(Observer* observer) OVERRIDE { - if (observer_ == observer) { - observer_ = NULL; - } - } - - virtual ConfigAvailability GetLatestProxyConfig( - ProxyConfig* config) OVERRIDE { - *config = config_; - return CONFIG_VALID; - } - - void IncrementConfigId() { - config_.set_id(config_.id() + 1); - observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID); - } - - private: - ProxyConfig config_; - Observer* observer_; -}; - -class HttpPipelinedNetworkTransactionTest : public testing::Test { - public: - HttpPipelinedNetworkTransactionTest() - : histograms_("a"), - pool_(1, 1, &histograms_, &factory_) { - } - - void Initialize(bool force_http_pipelining) { - // Normally, this code could just go in SetUp(). For a few of these tests, - // we change the default number of sockets per group. That needs to be done - // before we construct the HttpNetworkSession. - proxy_config_service_ = new SimpleProxyConfigService(); - proxy_service_.reset(new ProxyService(proxy_config_service_, NULL, NULL)); - ssl_config_ = new SSLConfigServiceDefaults; - auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory()); - - HttpNetworkSession::Params session_params; - session_params.client_socket_factory = &factory_; - session_params.proxy_service = proxy_service_.get(); - session_params.host_resolver = &mock_resolver_; - session_params.ssl_config_service = ssl_config_.get(); - session_params.http_auth_handler_factory = auth_handler_factory_.get(); - session_params.http_server_properties = - http_server_properties_.GetWeakPtr(); - session_params.force_http_pipelining = force_http_pipelining; - session_params.http_pipelining_enabled = true; - session_ = new HttpNetworkSession(session_params); - } - - void AddExpectedConnection(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count) { - DeterministicSocketData* data = new DeterministicSocketData( - reads, reads_count, writes, writes_count); - data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); - if (reads_count || writes_count) { - data->StopAfter(reads_count + writes_count); - } - factory_.AddSocketDataProvider(data); - data_vector_.push_back(data); - } - - enum RequestInfoOptions { - REQUEST_DEFAULT, - REQUEST_MAIN_RESOURCE, - }; - - HttpRequestInfo* GetRequestInfo( - const char* filename, RequestInfoOptions options = REQUEST_DEFAULT) { - std::string url = base::StringPrintf("http://localhost/%s", filename); - HttpRequestInfo* request_info = new HttpRequestInfo; - request_info->url = GURL(url); - request_info->method = "GET"; - if (options == REQUEST_MAIN_RESOURCE) { - request_info->load_flags = LOAD_MAIN_FRAME; - } - request_info_vector_.push_back(request_info); - return request_info; - } - - void ExpectResponse(const std::string& expected, - HttpNetworkTransaction& transaction, - IoMode io_mode) { - scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); - if (io_mode == ASYNC) { - EXPECT_EQ(ERR_IO_PENDING, transaction.Read(buffer.get(), expected.size(), - callback_.callback())); - data_vector_[0]->RunFor(1); - EXPECT_EQ(static_cast<int>(expected.length()), callback_.WaitForResult()); - } else { - EXPECT_EQ(static_cast<int>(expected.size()), - transaction.Read(buffer.get(), expected.size(), - callback_.callback())); - } - std::string actual(buffer->data(), expected.size()); - EXPECT_THAT(actual, StrEq(expected)); - EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(), - callback_.callback())); - } - - void CompleteTwoRequests(int data_index, int stop_at_step) { - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - EXPECT_EQ(OK, one_callback.WaitForResult()); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - TestCompletionCallback one_read_callback; - scoped_refptr<IOBuffer> buffer(new IOBuffer(8)); - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Read(buffer.get(), 8, - one_read_callback.callback())); - - data_vector_[data_index]->SetStop(stop_at_step); - data_vector_[data_index]->Run(); - EXPECT_EQ(8, one_read_callback.WaitForResult()); - data_vector_[data_index]->SetStop(10); - std::string actual(buffer->data(), 8); - EXPECT_THAT(actual, StrEq("one.html")); - EXPECT_EQ(OK, one_transaction->Read(buffer.get(), 8, - one_read_callback.callback())); - - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, SYNCHRONOUS); - } - - void CompleteFourRequests(RequestInfoOptions options) { - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("one.html", options), - one_callback.callback(), BoundNetLog())); - EXPECT_EQ(OK, one_callback.WaitForResult()); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html", options), - two_callback.callback(), BoundNetLog())); - - HttpNetworkTransaction three_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback three_callback; - EXPECT_EQ(ERR_IO_PENDING, - three_transaction.Start(GetRequestInfo("three.html", options), - three_callback.callback(), - BoundNetLog())); - - HttpNetworkTransaction four_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback four_callback; - EXPECT_EQ(ERR_IO_PENDING, - four_transaction.Start(GetRequestInfo("four.html", options), - four_callback.callback(), BoundNetLog())); - - ExpectResponse("one.html", *one_transaction.get(), SYNCHRONOUS); - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, SYNCHRONOUS); - EXPECT_EQ(OK, three_callback.WaitForResult()); - ExpectResponse("three.html", three_transaction, SYNCHRONOUS); - - one_transaction.reset(); - EXPECT_EQ(OK, four_callback.WaitForResult()); - ExpectResponse("four.html", four_transaction, SYNCHRONOUS); - } - - DeterministicMockClientSocketFactory factory_; - ClientSocketPoolHistograms histograms_; - MockTransportClientSocketPool pool_; - ScopedVector<DeterministicSocketData> data_vector_; - TestCompletionCallback callback_; - ScopedVector<HttpRequestInfo> request_info_vector_; - - SimpleProxyConfigService* proxy_config_service_; - scoped_ptr<ProxyService> proxy_service_; - MockHostResolver mock_resolver_; - scoped_refptr<SSLConfigService> ssl_config_; - scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_; - HttpServerPropertiesImpl http_server_properties_; - scoped_refptr<HttpNetworkSession> session_; -}; - -TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /test.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 9\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "test.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get()); - EXPECT_EQ(ERR_IO_PENDING, - transaction.Start(GetRequestInfo("test.html"), callback_.callback(), - BoundNetLog())); - EXPECT_EQ(OK, callback_.WaitForResult()); - ExpectResponse("test.html", transaction, SYNCHRONOUS); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(ASYNC, 4, "one.html"), - MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 7, "two.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - CompleteTwoRequests(0, 5); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) { - int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL); - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "one.html"), - MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 8, "two.html"), - MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"), - MockRead(SYNCHRONOUS, 11, "three.html"), - MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"), - MockRead(SYNCHRONOUS, 15, "four.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - CompleteFourRequests(REQUEST_DEFAULT); - - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, WontPipelineMainResource) { - int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL); - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 8, "GET /three.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "one.html"), - MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 7, "two.html"), - MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"), - MockRead(SYNCHRONOUS, 11, "three.html"), - MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"), - MockRead(SYNCHRONOUS, 15, "four.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - CompleteFourRequests(REQUEST_MAIN_RESOURCE); - - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), - MockRead(ASYNC, 2, "one.html"), - MockRead(SYNCHRONOUS, OK, 3), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - MockWrite writes2[] = { - MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads2[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "two.html"), - }; - AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); - - CompleteTwoRequests(0, 3); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(ASYNC, 4, "one.html"), - MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - MockWrite writes2[] = { - MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads2[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "two.html"), - }; - AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); - - CompleteTwoRequests(0, 5); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), - MockRead(SYNCHRONOUS, ERR_FAILED, 2), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - MockWrite writes2[] = { - MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads2[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "two.html"), - }; - AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); - - HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction.Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - EXPECT_EQ(OK, one_callback.WaitForResult()); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - scoped_refptr<IOBuffer> buffer(new IOBuffer(1)); - EXPECT_EQ(ERR_FAILED, - one_transaction.Read(buffer.get(), 1, callback_.callback())); - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, SYNCHRONOUS); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(ASYNC, ERR_FAILED, 0), - }; - AddExpectedConnection(NULL, 0, writes, arraysize(writes)); - - MockWrite writes2[] = { - MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads2[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "two.html"), - }; - AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); - - HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction.Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - data_vector_[0]->RunFor(1); - EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); - - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, SYNCHRONOUS); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, RedirectDrained) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(ASYNC, 4, "redirect"), - MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 7, "two.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("redirect.html"), - one_callback.callback(), BoundNetLog())); - EXPECT_EQ(OK, one_callback.WaitForResult()); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - one_transaction.reset(); - data_vector_[0]->RunFor(2); - data_vector_[0]->SetStop(10); - - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, SYNCHRONOUS); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 5, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n" - "Authorization: auth_token\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Authentication Required\r\n"), - MockRead(SYNCHRONOUS, 2, - "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"), - MockRead(SYNCHRONOUS, 3, "Content-Length: 20\r\n\r\n"), - MockRead(SYNCHRONOUS, 4, "needs authentication"), - MockRead(SYNCHRONOUS, 6, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 7, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 8, "one.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock; - std::string challenge_text = "Basic"; - HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), - challenge_text.end()); - GURL origin("localhost"); - EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge, - HttpAuth::AUTH_SERVER, - origin, - BoundNetLog())); - auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER); - - HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get()); - EXPECT_EQ(ERR_IO_PENDING, - transaction.Start(GetRequestInfo("one.html"), - callback_.callback(), - BoundNetLog())); - EXPECT_EQ(OK, callback_.WaitForResult()); - - AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")); - EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, callback_.callback())); - - ExpectResponse("one.html", transaction, SYNCHRONOUS); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, OldVersionDisablesPipelining) { - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /pipelined.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 14\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "pipelined.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - MockWrite writes2[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads2[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(ASYNC, 3, "one.html"), - MockRead(SYNCHRONOUS, OK, 4), - }; - AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); - - MockWrite writes3[] = { - MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads3[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "two.html"), - MockRead(SYNCHRONOUS, OK, 4), - }; - AddExpectedConnection(reads3, arraysize(reads3), writes3, arraysize(writes3)); - - HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction.Start(GetRequestInfo("pipelined.html"), - one_callback.callback(), BoundNetLog())); - EXPECT_EQ(OK, one_callback.WaitForResult()); - ExpectResponse("pipelined.html", one_transaction, SYNCHRONOUS); - - CompleteTwoRequests(1, 4); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, PipelinesImmediatelyIfKnownGood) { - // The first request gets us an HTTP/1.1. The next 3 test pipelining. When the - // 3rd request completes, we know pipelining is safe. After the first 4 - // complete, the 5th and 6th should then be immediately sent pipelined on a - // new HttpPipelinedConnection. - int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL); - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, 1); - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 16, "GET /second-pipeline-one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(SYNCHRONOUS, 17, "GET /second-pipeline-two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 3, "one.html"), - MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 8, "two.html"), - MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"), - MockRead(SYNCHRONOUS, 11, "three.html"), - MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"), - MockRead(SYNCHRONOUS, 15, "four.html"), - MockRead(ASYNC, 18, "HTTP/1.1 200 OK\r\n"), - MockRead(ASYNC, 19, "Content-Length: 24\r\n\r\n"), - MockRead(SYNCHRONOUS, 20, "second-pipeline-one.html"), - MockRead(SYNCHRONOUS, 21, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 22, "Content-Length: 24\r\n\r\n"), - MockRead(SYNCHRONOUS, 23, "second-pipeline-two.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - CompleteFourRequests(REQUEST_DEFAULT); - - HttpNetworkTransaction second_one_transaction( - DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback second_one_callback; - EXPECT_EQ(ERR_IO_PENDING, - second_one_transaction.Start( - GetRequestInfo("second-pipeline-one.html"), - second_one_callback.callback(), BoundNetLog())); - base::MessageLoop::current()->RunUntilIdle(); - - HttpNetworkTransaction second_two_transaction( - DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback second_two_callback; - EXPECT_EQ(ERR_IO_PENDING, - second_two_transaction.Start( - GetRequestInfo("second-pipeline-two.html"), - second_two_callback.callback(), BoundNetLog())); - - data_vector_[0]->RunFor(3); - EXPECT_EQ(OK, second_one_callback.WaitForResult()); - data_vector_[0]->StopAfter(100); - ExpectResponse("second-pipeline-one.html", second_one_transaction, - SYNCHRONOUS); - EXPECT_EQ(OK, second_two_callback.WaitForResult()); - ExpectResponse("second-pipeline-two.html", second_two_transaction, - SYNCHRONOUS); - - ClientSocketPoolManager::set_max_sockets_per_group( - HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets); -} - -class DataRunnerObserver : public base::MessageLoop::TaskObserver { - public: - DataRunnerObserver(DeterministicSocketData* data, int run_before_task) - : data_(data), - run_before_task_(run_before_task), - current_task_(0) { } - - virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE { - ++current_task_; - if (current_task_ == run_before_task_) { - data_->Run(); - base::MessageLoop::current()->RemoveTaskObserver(this); - } - } - - virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {} - - private: - DeterministicSocketData* data_; - int run_before_task_; - int current_task_; -}; - -TEST_F(HttpPipelinedNetworkTransactionTest, OpenPipelinesWhileBinding) { - // There was a racy crash in the pipelining code. This test recreates that - // race. The steps are: - // 1. The first request starts a pipeline and requests headers. - // 2. HttpStreamFactoryImpl::Job tries to bind a pending request to a new - // pipeline and queues a task to do so. - // 3. Before that task runs, the first request receives its headers and - // determines this host is probably capable of pipelining. - // 4. All of the hosts' pipelines are notified they have capacity in a loop. - // 5. On the first iteration, the first pipeline is opened up to accept new - // requests and steals the request from step #2. - // 6. The pipeline from #2 is deleted because it has no streams. - // 7. On the second iteration, the host tries to notify the pipeline from step - // #2 that it has capacity. This is a use-after-free. - Initialize(false); - - MockWrite writes[] = { - MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - MockWrite(ASYNC, 3, "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 4, "one.html"), - MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"), - MockRead(SYNCHRONOUS, 7, "two.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - AddExpectedConnection(NULL, 0, NULL, 0); - - HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction.Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - - data_vector_[0]->SetStop(2); - data_vector_[0]->Run(); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - // Posted tasks should be: - // 1. MockHostResolverBase::ResolveNow - // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1 - // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2 - // - // We need to make sure that the response that triggers OnPipelineFeedback(OK) - // is called in between when task #3 is scheduled and when it runs. The - // DataRunnerObserver does that. - DataRunnerObserver observer(data_vector_[0], 3); - base::MessageLoop::current()->AddTaskObserver(&observer); - data_vector_[0]->SetStop(4); - base::MessageLoop::current()->RunUntilIdle(); - data_vector_[0]->SetStop(10); - - EXPECT_EQ(OK, one_callback.WaitForResult()); - ExpectResponse("one.html", one_transaction, SYNCHRONOUS); - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, SYNCHRONOUS); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ProxyChangesWhileConnecting) { - Initialize(false); - - DeterministicSocketData data(NULL, 0, NULL, 0); - data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED)); - factory_.AddSocketDataProvider(&data); - - DeterministicSocketData data2(NULL, 0, NULL, 0); - data2.set_connect_data(MockConnect(ASYNC, ERR_FAILED)); - factory_.AddSocketDataProvider(&data2); - - HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get()); - EXPECT_EQ(ERR_IO_PENDING, - transaction.Start(GetRequestInfo("test.html"), callback_.callback(), - BoundNetLog())); - - proxy_config_service_->IncrementConfigId(); - - EXPECT_EQ(ERR_FAILED, callback_.WaitForResult()); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineSharesConnection) { - Initialize(true); - - MockWrite writes[] = { - MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n" - "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"), - MockRead(ASYNC, 3, "one.html"), - MockRead(ASYNC, 4, "HTTP/1.1 200 OK\r\n"), - MockRead(ASYNC, 5, "Content-Length: 8\r\n\r\n"), - MockRead(ASYNC, 6, "two.html"), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - data_vector_[0]->RunFor(3); // Send + 2 lines of headers. - EXPECT_EQ(OK, one_callback.WaitForResult()); - ExpectResponse("one.html", *one_transaction.get(), ASYNC); - one_transaction.reset(); - - data_vector_[0]->RunFor(2); // 2 lines of headers. - EXPECT_EQ(OK, two_callback.WaitForResult()); - ExpectResponse("two.html", two_transaction, ASYNC); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, - ForcedPipelineConnectionErrorFailsBoth) { - Initialize(true); - - DeterministicSocketData data(NULL, 0, NULL, 0); - data.set_connect_data(MockConnect(ASYNC, ERR_FAILED)); - factory_.AddSocketDataProvider(&data); - - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - data.Run(); - EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); - EXPECT_EQ(ERR_FAILED, two_callback.WaitForResult()); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineEvictionIsFatal) { - Initialize(true); - - MockWrite writes[] = { - MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n" - "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(ASYNC, ERR_FAILED, 1), - }; - AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); - - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - - HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get()); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction.Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - data_vector_[0]->RunFor(2); - EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); - one_transaction.reset(); - EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult()); -} - -TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineOrder) { - Initialize(true); - - MockWrite writes[] = { - MockWrite(ASYNC, 0, - "GET /one.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n" - "GET /two.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n" - "GET /three.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n" - "GET /four.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "Connection: keep-alive\r\n\r\n" - ), - }; - MockRead reads[] = { - MockRead(ASYNC, ERR_FAILED, 1), - }; - DeterministicSocketData data( - reads, arraysize(reads), writes, arraysize(writes)); - data.set_connect_data(MockConnect(ASYNC, OK)); - factory_.AddSocketDataProvider(&data); - - scoped_ptr<HttpNetworkTransaction> one_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback one_callback; - EXPECT_EQ(ERR_IO_PENDING, - one_transaction->Start(GetRequestInfo("one.html"), - one_callback.callback(), BoundNetLog())); - - scoped_ptr<HttpNetworkTransaction> two_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback two_callback; - EXPECT_EQ(ERR_IO_PENDING, - two_transaction->Start(GetRequestInfo("two.html"), - two_callback.callback(), BoundNetLog())); - - scoped_ptr<HttpNetworkTransaction> three_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback three_callback; - EXPECT_EQ(ERR_IO_PENDING, - three_transaction->Start(GetRequestInfo("three.html"), - three_callback.callback(), BoundNetLog())); - - scoped_ptr<HttpNetworkTransaction> four_transaction( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); - TestCompletionCallback four_callback; - EXPECT_EQ(ERR_IO_PENDING, - four_transaction->Start(GetRequestInfo("four.html"), - four_callback.callback(), BoundNetLog())); - - data.RunFor(3); - EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); - one_transaction.reset(); - EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult()); - two_transaction.reset(); - EXPECT_EQ(ERR_PIPELINE_EVICTION, three_callback.WaitForResult()); - three_transaction.reset(); - EXPECT_EQ(ERR_PIPELINE_EVICTION, four_callback.WaitForResult()); -} - -} // anonymous namespace - -} // namespace net |