[net] Add preconnect error handling tests when uploading.
This CL extends
HttpNetworkTransactionTest::PreconnectErrorResendRequestTest() to
confirm upload success when the first attempt failed over both H/1 and
H/2.
This is a preparation to add caching mechanism in
ChunkedDataPipeUploadDataStream: crrev.com/c/2269622
Bug: 1077174
Change-Id: I75b277295652e87de7f2b6cde4e911d2669e9839
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2334726
Commit-Queue: Yoichi Osato <[email protected]>
Reviewed-by: Matt Menke <[email protected]>
Cr-Commit-Position: refs/heads/master@{#794809}
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 26d16a20..b883035 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -460,7 +460,8 @@
// other argument should be NULL.
void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
const MockRead* read_failure,
- bool use_spdy);
+ bool use_spdy,
+ bool upload = false);
SimpleGetHelperResult SimpleGetHelperForData(
base::span<StaticSocketDataProvider*> providers) {
@@ -1883,13 +1884,24 @@
void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
const MockWrite* write_failure,
const MockRead* read_failure,
- bool use_spdy) {
+ bool use_spdy,
+ bool chunked_upload) {
+ SpdyTestUtil spdy_util;
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.foo.com/");
request.traffic_annotation =
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+ const char upload_data[] = "foobar";
+ ChunkedUploadDataStream upload_data_stream(0);
+ if (chunked_upload) {
+ request.method = "POST";
+ upload_data_stream.AppendData(upload_data, base::size(upload_data) - 1,
+ true);
+ request.upload_data_stream = &upload_data_stream;
+ }
+
RecordingTestNetLog net_log;
session_deps_.net_log = &net_log;
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -1904,17 +1916,32 @@
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
// SPDY versions of the request and response.
- spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
- request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
+
+ spdy::SpdyHeaderBlock spdy_post_header_block;
+ spdy_post_header_block[spdy::kHttp2MethodHeader] = "POST";
+ spdy_util.AddUrlToHeaderBlock(request.url.spec(), &spdy_post_header_block);
+ spdy::SpdySerializedFrame spdy_request(
+ chunked_upload
+ ? spdy_util.ConstructSpdyHeaders(1, std::move(spdy_post_header_block),
+ DEFAULT_PRIORITY, false)
+ : spdy_util.ConstructSpdyGet(request.url.spec().c_str(), 1,
+ DEFAULT_PRIORITY));
+
+ spdy::SpdySerializedFrame spdy_request_body(
+ spdy_util.ConstructSpdyDataFrame(1, "foobar", true));
spdy::SpdySerializedFrame spdy_response(
- spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
spdy::SpdySerializedFrame spdy_data(
- spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
+ spdy_util.ConstructSpdyDataFrame(1, "hello", true));
// HTTP/1.1 versions of the request and response.
- const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
+ const std::string http_request =
+ std::string(chunked_upload ? "POST" : "GET") +
+ " / HTTP/1.1\r\n"
"Host: www.foo.com\r\n"
- "Connection: keep-alive\r\n\r\n";
+ "Connection: keep-alive\r\n" +
+ (chunked_upload ? "Transfer-Encoding: chunked\r\n\r\n" : "\r\n");
+ const char* kHttpRequest = http_request.c_str();
const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
const char kHttpData[] = "hello";
@@ -1928,8 +1955,14 @@
ASSERT_TRUE(read_failure);
if (use_spdy) {
data1_writes.push_back(CreateMockWrite(spdy_request));
+ if (chunked_upload)
+ data1_writes.push_back(CreateMockWrite(spdy_request_body));
} else {
data1_writes.push_back(MockWrite(kHttpRequest));
+ if (chunked_upload) {
+ data1_writes.push_back(MockWrite("6\r\nfoobar\r\n"));
+ data1_writes.push_back(MockWrite("0\r\n\r\n"));
+ }
}
data1_reads.push_back(*read_failure);
}
@@ -1941,19 +1974,25 @@
std::vector<MockWrite> data2_writes;
if (use_spdy) {
- data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
-
- data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
- data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
- data2_reads.push_back(MockRead(ASYNC, OK, 3));
+ int seq = 0;
+ data2_writes.push_back(CreateMockWrite(spdy_request, seq++, ASYNC));
+ if (chunked_upload)
+ data2_writes.push_back(CreateMockWrite(spdy_request_body, seq++, ASYNC));
+ data2_reads.push_back(CreateMockRead(spdy_response, seq++, ASYNC));
+ data2_reads.push_back(CreateMockRead(spdy_data, seq++, ASYNC));
+ data2_reads.push_back(MockRead(ASYNC, OK, seq++));
} else {
+ int seq = 0;
data2_writes.push_back(
- MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
-
+ MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), seq++));
+ if (chunked_upload) {
+ data2_writes.push_back(MockWrite(ASYNC, "6\r\nfoobar\r\n", 11, seq++));
+ data2_writes.push_back(MockWrite(ASYNC, "0\r\n\r\n", 5, seq++));
+ }
data2_reads.push_back(
- MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
- data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
- data2_reads.push_back(MockRead(ASYNC, OK, 3));
+ MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), seq++));
+ data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), seq++));
+ data2_reads.push_back(MockRead(ASYNC, OK, seq++));
}
SequencedSocketData data2(data2_reads, data2_writes);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
@@ -2118,22 +2157,34 @@
TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
- PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
+ PreconnectErrorResendRequestTest(&write_failure, nullptr,
+ false /* use_spdy */);
+ PreconnectErrorResendRequestTest(
+ &write_failure, nullptr, false /* use_spdy */, true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
- PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure,
+ false /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
MockRead read_failure(SYNCHRONOUS, OK); // EOF
- PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure,
+ false /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
MockRead read_failure(ASYNC, OK); // EOF
- PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure,
+ false /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
+ true /* chunked_upload */);
}
// Make sure that on a 408 response (Request Timeout), the request is retried,
@@ -2145,27 +2196,39 @@
"Content-Length: 6\r\n\r\n"
"Pickle");
KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
- PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure,
+ false /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
- PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
+ PreconnectErrorResendRequestTest(&write_failure, nullptr,
+ true /* use_spdy */);
+ PreconnectErrorResendRequestTest(&write_failure, nullptr, true /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
- PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
MockRead read_failure(SYNCHRONOUS, OK); // EOF
- PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
MockRead read_failure(ASYNC, OK); // EOF
- PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
+ PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
+ true /* chunked_upload */);
}
TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {