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; |