summaryrefslogtreecommitdiffstats
path: root/net/http/http_network_transaction_unittest.cc
diff options
context:
space:
mode:
authorvandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-16 19:48:34 +0000
committervandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-16 19:48:34 +0000
commit878d73010d3e415857730205d0892ad6ecf1a26d (patch)
tree76a5be7369270360ad61cd8954e81f651ead3fe8 /net/http/http_network_transaction_unittest.cc
parent5829e67b3a7492d92ed202c0cd53268723afce87 (diff)
downloadchromium_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.cc256
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