summaryrefslogtreecommitdiffstats
path: root/net/http/http_network_transaction_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/http/http_network_transaction_unittest.cc')
-rw-r--r--net/http/http_network_transaction_unittest.cc483
1 files changed, 483 insertions, 0 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 3100297..c1112d0 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -12605,4 +12605,487 @@ TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
}
+TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+// This test makes sure the retry logic doesn't trigger when reading an error
+// response from a server that rejected a POST with a CONNECTION_RESET.
+TEST_P(HttpNetworkTransactionTest,
+ PostReadsErrorResponseAfterResetOnReusedSocket) {
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ MockWrite data_writes[] = {
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 Peachy\r\n"
+ "Content-Length: 14\r\n\r\n"),
+ MockRead("first response"),
+ MockRead("HTTP/1.1 400 Not OK\r\n"
+ "Content-Length: 15\r\n\r\n"),
+ MockRead("second response"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+ HttpRequestInfo request1;
+ request1.method = "GET";
+ request1.url = GURL("http://www.foo.com/");
+ request1.load_flags = 0;
+
+ scoped_ptr<HttpTransaction> trans1(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response1 = trans1->GetResponseInfo();
+ ASSERT_TRUE(response1 != NULL);
+
+ EXPECT_TRUE(response1->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
+
+ std::string response_data1;
+ rv = ReadTransaction(trans1.get(), &response_data1);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("first response", response_data1);
+ // Delete the transaction to release the socket back into the socket pool.
+ trans1.reset();
+
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request2;
+ request2.method = "POST";
+ request2.url = GURL("http://www.foo.com/");
+ request2.upload_data_stream = &upload_data_stream;
+ request2.load_flags = 0;
+
+ scoped_ptr<HttpTransaction> trans2(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response2 = trans2->GetResponseInfo();
+ ASSERT_TRUE(response2 != NULL);
+
+ EXPECT_TRUE(response2->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
+
+ std::string response_data2;
+ rv = ReadTransaction(trans2.get(), &response_data2);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("second response", response_data2);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+ PostReadsErrorResponseAfterResetPartialBodySent) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"
+ "fo"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+// This tests the more common case than the previous test, where headers and
+// body are not merged into a single request.
+TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Transfer-Encoding: chunked\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ // Make sure the headers are sent before adding a chunk. This ensures that
+ // they can't be merged with the body in a single send. Not currently
+ // necessary since a chunked body is never merged with headers, but this makes
+ // the test more future proof.
+ base::RunLoop().RunUntilIdle();
+
+ upload_data_stream.AppendChunk("last chunk", 10, true);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+ PostIgnoresNonErrorResponseAfterResetAnd100) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
+ MockRead("HTTP/1.0 302 Redirect\r\n"),
+ MockRead("Location: http://somewhere-else.com/\r\n"),
+ MockRead("Content-Length: 0\r\n\r\n"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP 0.9 rocks!"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
} // namespace net