diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-16 19:48:34 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-16 19:48:34 +0000 |
commit | 878d73010d3e415857730205d0892ad6ecf1a26d (patch) | |
tree | 76a5be7369270360ad61cd8954e81f651ead3fe8 /net/http/http_network_transaction_unittest.cc | |
parent | 5829e67b3a7492d92ed202c0cd53268723afce87 (diff) | |
download | chromium_src-878d73010d3e415857730205d0892ad6ecf1a26d.zip chromium_src-878d73010d3e415857730205d0892ad6ecf1a26d.tar.gz chromium_src-878d73010d3e415857730205d0892ad6ecf1a26d.tar.bz2 |
Refactor HttpNetworkTransaction so that HttpStream is responsible for parsing the Http traffic. HttpBasicStream delegates parsing to HttpStreamParser in preparation for HttpPipelinedStream.
BUG=13289
TEST=unittests
Review URL: http://codereview.chromium.org/249031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29316 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http/http_network_transaction_unittest.cc')
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 256 |
1 files changed, 224 insertions, 32 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index a3a4647..b47e34a 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -12,8 +12,10 @@ #include "net/base/test_completion_callback.h" #include "net/base/upload_data.h" #include "net/http/http_auth_handler_ntlm.h" +#include "net/http/http_basic_stream.h" #include "net/http/http_network_session.h" #include "net/http/http_network_transaction.h" +#include "net/http/http_stream.h" #include "net/http/http_transaction_unittest.h" #include "net/proxy/proxy_config_service_fixed.h" #include "net/socket/client_socket_factory.h" @@ -320,6 +322,24 @@ TEST_F(HttpNetworkTransactionTest, StopsReading204) { EXPECT_EQ("", out.response_data); } +// A simple request using chunked encoding with some extra data after. +// (Like might be seen in a pipelined response.) +TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) { + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"), + MockRead("5\r\nHello\r\n"), + MockRead("1\r\n"), + MockRead(" \r\n"), + MockRead("5\r\nworld\r\n"), + MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), + MockRead(false, OK), + }; + SimpleGetHelperResult out = SimpleGetHelper(data_reads); + EXPECT_EQ(OK, out.rv); + EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); + EXPECT_EQ("Hello world", out.response_data); +} + // Do a request using the HEAD method. Verify that we don't try to read the // message body (since HEAD has none). TEST_F(HttpNetworkTransactionTest, Head) { @@ -471,7 +491,7 @@ TEST_F(HttpNetworkTransactionTest, Ignores100) { // This test is almost the same as Ignores100 above, but the response contains // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is -// HTTP/1.1. +// HTTP/1.1 and the two status headers are read in one read. TEST_F(HttpNetworkTransactionTest, Ignores1xx) { SessionDependencies session_deps; scoped_ptr<HttpTransaction> trans( @@ -483,8 +503,8 @@ TEST_F(HttpNetworkTransactionTest, Ignores1xx) { request.load_flags = 0; MockRead data_reads[] = { - MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"), - MockRead("HTTP/1.1 200 OK\r\n\r\n"), + MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n" + "HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"), MockRead(false, OK), }; @@ -2678,53 +2698,40 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) { new HttpNetworkTransaction(CreateSession(&session_deps))); // Setup some state (which we expect ResetStateForRestart() will clear). - trans->header_buf_->Realloc(10); - trans->header_buf_capacity_ = 10; - trans->header_buf_len_ = 3; - trans->header_buf_body_offset_ = 11; - trans->header_buf_http_offset_ = 0; - trans->response_body_length_ = 100; - trans->response_body_read_ = 1; trans->read_buf_ = new IOBuffer(15); trans->read_buf_len_ = 15; - trans->request_headers_->headers_ = "Authorization: NTLM"; - trans->request_headers_bytes_sent_ = 3; + trans->request_headers_ = "Authorization: NTLM"; // Setup state in response_ - trans->response_.auth_challenge = new AuthChallengeInfo(); - trans->response_.ssl_info.cert_status = -15; - trans->response_.response_time = base::Time::Now(); - trans->response_.was_cached = true; // (Wouldn't ever actually be true...) + trans->http_stream_.reset(new HttpBasicStream(NULL)); + HttpResponseInfo* response = trans->http_stream_->GetResponseInfo(); + response->auth_challenge = new AuthChallengeInfo(); + response->ssl_info.cert_status = -15; + response->response_time = base::Time::Now(); + response->was_cached = true; // (Wouldn't ever actually be true...) { // Setup state for response_.vary_data HttpRequestInfo request; std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n"); std::replace(temp.begin(), temp.end(), '\n', '\0'); - scoped_refptr<HttpResponseHeaders> response = new HttpResponseHeaders(temp); + scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp); request.extra_headers = "Foo: 1\nbar: 23"; - EXPECT_TRUE(trans->response_.vary_data.Init(request, *response)); + EXPECT_TRUE(response->vary_data.Init(request, *headers)); } // Cause the above state to be reset. trans->ResetStateForRestart(); // Verify that the state that needed to be reset, has been reset. - EXPECT_TRUE(trans->header_buf_->headers() == NULL); - EXPECT_EQ(0, trans->header_buf_capacity_); - EXPECT_EQ(0, trans->header_buf_len_); - EXPECT_EQ(-1, trans->header_buf_body_offset_); - EXPECT_EQ(-1, trans->header_buf_http_offset_); - EXPECT_EQ(-1, trans->response_body_length_); - EXPECT_EQ(0, trans->response_body_read_); + response = trans->http_stream_->GetResponseInfo(); EXPECT_TRUE(trans->read_buf_.get() == NULL); EXPECT_EQ(0, trans->read_buf_len_); - EXPECT_EQ("", trans->request_headers_->headers_); - EXPECT_EQ(0U, trans->request_headers_bytes_sent_); - EXPECT_TRUE(trans->response_.auth_challenge.get() == NULL); - EXPECT_TRUE(trans->response_.headers.get() == NULL); - EXPECT_EQ(false, trans->response_.was_cached); - EXPECT_EQ(0, trans->response_.ssl_info.cert_status); - EXPECT_FALSE(trans->response_.vary_data.is_valid()); + EXPECT_EQ(0U, trans->request_headers_.size()); + EXPECT_TRUE(response->auth_challenge.get() == NULL); + EXPECT_TRUE(response->headers.get() == NULL); + EXPECT_EQ(false, response->was_cached); + EXPECT_EQ(0, response->ssl_info.cert_status); + EXPECT_FALSE(response->vary_data.is_valid()); } // Test HTTPS connections to a site with a bad certificate @@ -3595,4 +3602,189 @@ TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) { EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); } +// Make sure we can handle an error when writing the request. +TEST_F(HttpNetworkTransactionTest, RequestWriteError) { + SessionDependencies session_deps; + scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.foo.com/"); + request.load_flags = 0; + + MockWrite write_failure[] = { + MockWrite(true, ERR_CONNECTION_RESET), + }; + StaticMockSocket data(NULL, write_failure); + session_deps.socket_factory.AddMockSocket(&data); + + TestCompletionCallback callback; + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + int rv = trans->Start(&request, &callback, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(ERR_CONNECTION_RESET, rv); +} + +// Check that a connection closed after the start of the headers finishes ok. +TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { + SessionDependencies session_deps; + scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.foo.com/"); + request.load_flags = 0; + + MockRead data_reads[] = { + MockRead("HTTP/1."), + MockRead(false, OK), + }; + + StaticMockSocket data(data_reads, NULL); + session_deps.socket_factory.AddMockSocket(&data); + + TestCompletionCallback callback; + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + int rv = trans->Start(&request, &callback, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + EXPECT_TRUE(response != NULL); + + EXPECT_TRUE(response->headers != NULL); + EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); + + std::string response_data; + rv = ReadTransaction(trans.get(), &response_data); + EXPECT_EQ(OK, rv); + EXPECT_EQ("", response_data); +} + +// Make sure that a dropped connection while draining the body for auth +// restart does the right thing. +TEST_F(HttpNetworkTransactionTest, DrainResetOK) { + SessionDependencies session_deps; + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.google.com/"); + request.load_flags = 0; + + MockWrite data_writes1[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + + MockRead data_reads1[] = { + MockRead("HTTP/1.1 401 Unauthorized\r\n"), + MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 14\r\n\r\n"), + MockRead("Unauth"), + MockRead(true, ERR_CONNECTION_RESET), + }; + + StaticMockSocket data1(data_reads1, data_writes1); + session_deps.socket_factory.AddMockSocket(&data1); + + // After calling trans->RestartWithAuth(), this is the request we should + // be issuing -- the final header line contains the credentials. + MockWrite data_writes2[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Connection: keep-alive\r\n" + "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), + }; + + // Lastly, the server responds with the actual content. + MockRead data_reads2[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 100\r\n\r\n"), + MockRead(false, OK), + }; + + StaticMockSocket data2(data_reads2, data_writes2); + session_deps.socket_factory.AddMockSocket(&data2); + + TestCompletionCallback callback1; + + int rv = trans->Start(&request, &callback1, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback1.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + EXPECT_FALSE(response == NULL); + + // The password prompt info should have been set in response->auth_challenge. + EXPECT_FALSE(response->auth_challenge.get() == NULL); + + EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); + EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); + EXPECT_EQ(L"basic", response->auth_challenge->scheme); + + TestCompletionCallback callback2; + + rv = trans->RestartWithAuth(L"foo", L"bar", &callback2); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback2.WaitForResult(); + EXPECT_EQ(OK, rv); + + response = trans->GetResponseInfo(); + EXPECT_FALSE(response == NULL); + EXPECT_TRUE(response->auth_challenge.get() == NULL); + EXPECT_EQ(100, response->headers->GetContentLength()); +} + +// Test HTTPS connections going through a proxy that sends extra data. +TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) { + SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("https://www.google.com/"); + request.load_flags = 0; + + MockRead proxy_reads[] = { + MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"), + MockRead(false, OK) + }; + + StaticMockSocket data(proxy_reads, NULL); + MockSSLSocket ssl(true, OK); + + session_deps.socket_factory.AddMockSocket(&data); + session_deps.socket_factory.AddMockSSLSocket(&ssl); + + TestCompletionCallback callback; + + session_deps.socket_factory.ResetNextMockIndexes(); + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + int rv = trans->Start(&request, &callback, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); +} + } // namespace net |