Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Unified Diff: content/browser/loader/mojo_async_resource_handler_unittest.cc

Issue 2738973002: Allow MojoAsyncResourceHandler::OnWillRead to complete asyncronously (Closed)
Patch Set: Merge Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/loader/mojo_async_resource_handler.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/loader/mojo_async_resource_handler_unittest.cc
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc
index 2a29d61f35740c778053c7a7be643e7cb5bccd49..46c4cf05e278d5d7288fccdd2830dcfc85d56581 100644
--- a/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -585,8 +585,7 @@ TEST_F(MojoAsyncResourceHandlerTest,
contents.append(buffer, read_size);
}
EXPECT_EQ(data, contents);
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
+ EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
}
TEST_F(MojoAsyncResourceHandlerTest,
@@ -723,8 +722,10 @@ TEST_F(MojoAsyncResourceHandlerTest, OutOfBandCancelDuringBodyTransmission) {
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
std::string data(mock_loader_->io_buffer_size(), 'a');
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
mock_loader_->OnReadCompleted(data));
+ ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->OnWillRead());
url_loader_client_.RunUntilResponseBodyArrived();
ASSERT_TRUE(url_loader_client_.response_body().is_valid());
@@ -764,45 +765,122 @@ TEST_F(MojoAsyncResourceHandlerTest, BeginWriteFailsOnWillRead) {
TEST_F(MojoAsyncResourceHandlerTest, BeginWriteReturnsShouldWaitOnWillRead) {
handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
+
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
+
+ // Bytes are read one-at-a-time, and each OnWillRead() call completes
+ // asynchronously. Note that this loop runs 4 times (once for the terminal
+ // '\0').
+ const char kReadData[] = "ABC";
+ for (const char read_char : kReadData) {
+ handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
+ ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->OnWillRead());
+ EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing());
+
+ handler_->ResetBeginWriteExpectation();
+ handler_->OnWritableForTesting();
+ EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
+
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnReadCompleted(std::string(1, read_char)));
+ url_loader_client_.RunUntilResponseBodyArrived();
+
+ // Keep on trying to read the data until it succeeds.
+ while (true) {
+ char buffer[16];
+ uint32_t read_size = sizeof(buffer);
+ MojoResult result =
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
+ &read_size, MOJO_READ_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_SHOULD_WAIT) {
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ ASSERT_EQ(1u, read_size);
+ EXPECT_EQ(read_char, buffer[0]);
+ break;
+ }
+
+ base::RunLoop().RunUntilIdle();
+ }
+ }
+
+ // Should only count as one in-flight request.
+ EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing());
+
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(
+ net::URLRequestStatus::FromError(net::OK)));
+
+ url_loader_client_.RunUntilComplete();
+ EXPECT_TRUE(url_loader_client_.has_received_completion());
+
+ handler_.reset();
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
}
+// Same as above, but after the first OnWriteable() call, BeginWrite() indicates
+// should wait again. Unclear if this can happen in practice, but seems best to
+// support it.
TEST_F(MojoAsyncResourceHandlerTest,
- BeginWriteReturnsShouldWaitOnWillReadAndThenReturnsOK) {
+ BeginWriteReturnsShouldWaitTwiceOnWillRead) {
handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
+
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
- size_t written = 0;
- while (true) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- MockResourceLoader::Status result = mock_loader_->OnReadCompleted(
- std::string(mock_loader_->io_buffer_size(), 'X'));
- written += mock_loader_->io_buffer_size();
- if (result == MockResourceLoader::Status::CALLBACK_PENDING)
- break;
- ASSERT_EQ(MockResourceLoader::Status::IDLE, result);
- }
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
- url_loader_client_.RunUntilResponseBodyArrived();
- ASSERT_TRUE(url_loader_client_.response_body().is_valid());
- handler_->ResetBeginWriteExpectation();
- handler_->OnWritableForTesting();
+ // Bytes are read one-at-a-time, and each OnWillRead() call completes
+ // asynchronously. Note that this loop runs 4 times (once for the terminal
+ // '\0').
+ const char kReadData[] = "ABC";
+ for (const char read_char : kReadData) {
+ handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
+ ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->OnWillRead());
+ EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing());
+
+ handler_->OnWritableForTesting();
+ EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->status());
+
+ handler_->ResetBeginWriteExpectation();
+ handler_->OnWritableForTesting();
+ EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
+
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnReadCompleted(std::string(1, read_char)));
+ url_loader_client_.RunUntilResponseBodyArrived();
+
+ // Keep on trying to read the data until it succeeds.
+ while (true) {
+ char buffer[16];
+ uint32_t read_size = sizeof(buffer);
+ MojoResult result =
+ mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
+ &read_size, MOJO_READ_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_SHOULD_WAIT) {
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ ASSERT_EQ(1u, read_size);
+ EXPECT_EQ(read_char, buffer[0]);
+ break;
+ }
- std::string actual;
- while (actual.size() < written) {
- char buf[16];
- uint32_t read_size = sizeof(buf);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
- ASSERT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT);
- if (result == MOJO_RESULT_OK)
- actual.append(buf, read_size);
- base::RunLoop().RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ }
}
- EXPECT_EQ(std::string(written, 'X'), actual);
- EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
+ // Should only count as one in-flight request.
+ EXPECT_EQ(1, rdh_.num_in_flight_requests_for_testing());
+
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(
+ net::URLRequestStatus::FromError(net::OK)));
+
+ url_loader_client_.RunUntilComplete();
+ EXPECT_TRUE(url_loader_client_.has_received_completion());
+
+ handler_.reset();
+ EXPECT_EQ(0, rdh_.num_in_flight_requests_for_testing());
}
TEST_F(MojoAsyncResourceHandlerTest,
@@ -869,7 +947,7 @@ TEST_F(MojoAsyncResourceHandlerTest,
mock_loader_->WaitUntilIdleOrCanceled();
EXPECT_FALSE(url_loader_client_.has_received_completion());
EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
+ EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, mock_loader_->error_code());
}
TEST_F(MojoAsyncResourceHandlerUploadTest, UploadProgressHandling) {
@@ -942,20 +1020,18 @@ TEST_F(MojoAsyncResourceHandlerTest, SetPriority) {
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
OnWillReadWithLongContents) {
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+
std::string expected;
for (int i = 0; i < 3 * mock_loader_->io_buffer_size() + 2; ++i)
expected += ('A' + i % 26);
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnReadCompleted(0));
-
size_t written = 0;
std::string actual;
while (actual.size() < expected.size()) {
while (written < expected.size() &&
mock_loader_->status() == MockResourceLoader::Status::IDLE) {
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- const size_t to_be_written =
+ size_t to_be_written =
std::min(static_cast<size_t>(mock_loader_->io_buffer_size()),
expected.size() - written);
@@ -993,10 +1069,16 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+ // Whether the next OnReadCompleted call or OnWillRead returns the error
+ // depends on whether or not an intermediary buffer is being used by the
+ // MojoAsyncResourceHandler.
handler_->set_begin_write_expectation(MOJO_RESULT_UNKNOWN);
- ASSERT_EQ(MockResourceLoader::Status::CANCELED,
- mock_loader_->OnReadCompleted(
- std::string(mock_loader_->io_buffer_size(), 'A')));
+ MockResourceLoader::Status result = mock_loader_->OnReadCompleted(
+ std::string(mock_loader_->io_buffer_size(), 'A'));
+ if (result == MockResourceLoader::Status::CANCELED)
+ return;
+ ASSERT_EQ(MockResourceLoader::Status::IDLE, result);
+ ASSERT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->OnWillRead());
}
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
@@ -1004,21 +1086,32 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+ // Whether the next OnReadCompleted call or OnWillRead call completes
+ // asynchronously depends on whether or not an intermediary buffer is being
+ // used by the MojoAsyncResourceHandler.
handler_->set_begin_write_expectation(MOJO_RESULT_SHOULD_WAIT);
+ MockResourceLoader::Status result = mock_loader_->OnReadCompleted(
+ std::string(mock_loader_->io_buffer_size() - 1, 'A'));
+ if (result == MockResourceLoader::Status::CALLBACK_PENDING)
+ return;
+
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(
- std::string(mock_loader_->io_buffer_size(), 'A')));
+ mock_loader_->OnWillRead());
}
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
BeginWriteFailsOnResume) {
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnReadCompleted(0));
while (true) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- MockResourceLoader::Status result = mock_loader_->OnReadCompleted(
+ // Whether the next OnReadCompleted call or OnWillRead call completes
+ // asynchronously depends on whether or not an intermediary buffer is being
+ // used by the MojoAsyncResourceHandler.
+ MockResourceLoader::Status result = mock_loader_->OnWillRead();
+ if (result == MockResourceLoader::Status::CALLBACK_PENDING)
+ break;
+ ASSERT_EQ(MockResourceLoader::Status::IDLE, result);
+ result = mock_loader_->OnReadCompleted(
std::string(mock_loader_->io_buffer_size(), 'A'));
if (result == MockResourceLoader::Status::CALLBACK_PENDING)
break;
@@ -1039,16 +1132,25 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
base::RunLoop().RunUntilIdle();
}
+ if (mock_loader_->status() == MockResourceLoader::Status::IDLE)
+ EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->OnWillRead());
+
EXPECT_FALSE(url_loader_client_.has_received_completion());
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
+ EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, mock_loader_->error_code());
}
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, CancelWhileWaiting) {
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
while (true) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- MockResourceLoader::Status result = mock_loader_->OnReadCompleted(
+ // Whether the next OnReadCompleted call or OnWillRead call completes
+ // asynchronously depends on whether or not an intermediary buffer is being
+ // used by the MojoAsyncResourceHandler.
+ MockResourceLoader::Status result = mock_loader_->OnWillRead();
+ if (result == MockResourceLoader::Status::CALLBACK_PENDING)
+ break;
+ ASSERT_EQ(MockResourceLoader::Status::IDLE, result);
+ result = mock_loader_->OnReadCompleted(
std::string(mock_loader_->io_buffer_size(), 'A'));
if (result == MockResourceLoader::Status::CALLBACK_PENDING)
break;
« no previous file with comments | « content/browser/loader/mojo_async_resource_handler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698