| Index: net/http/http_network_transaction_unittest.cc
|
| ===================================================================
|
| --- net/http/http_network_transaction_unittest.cc (revision 29289)
|
| +++ net/http/http_network_transaction_unittest.cc (working copy)
|
| @@ -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 @@
|
| 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 @@
|
|
|
| // 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 @@
|
| 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 @@
|
| 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 @@
|
| 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
|
|
|