Index: chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc |
=================================================================== |
--- chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc (revision 9239) |
+++ chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc (working copy) |
@@ -104,7 +104,7 @@ |
URLRequest::RegisterProtocolFactory("test", NULL); |
RendererSecurityPolicy::GetInstance()->Remove(0); |
- // The plugin lib is automatically loaded during these test |
+ // The plugin lib is automatically loaded during these test |
// and we want a clean environment for other tests. |
ChromePluginLib::UnloadAllPlugins(); |
@@ -194,6 +194,8 @@ |
// Tests whether many messages get dispatched properly. |
TEST_F(ResourceDispatcherHostTest, TestMany) { |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2()); |
MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
@@ -201,6 +203,8 @@ |
// flush all the pending requests |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
// sorts out all the messages we saw by request |
ResourceIPCAccumulator::ClassifiedMessages msgs; |
accum_.GetClassifiedMessages(&msgs); |
@@ -218,6 +222,8 @@ |
TEST_F(ResourceDispatcherHostTest, Cancel) { |
ResourceDispatcherHost host(NULL); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2()); |
MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
@@ -225,7 +231,10 @@ |
// flush all the pending requests |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
+ MessageLoop::current()->RunAllPending(); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
ResourceIPCAccumulator::ClassifiedMessages msgs; |
accum_.GetClassifiedMessages(&msgs); |
@@ -235,28 +244,19 @@ |
CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); |
CheckSuccessfulRequest(msgs[2], URLRequestTestJob::test_data_3()); |
- // Check that request 2 got canceled before it finished reading, which gives |
- // us 1 ReceivedResponse message. |
- ASSERT_EQ(1, msgs[1].size()); |
+ // Check that request 2 got canceled. |
+ ASSERT_EQ(2, msgs[1].size()); |
ASSERT_EQ(ViewMsg_Resource_ReceivedResponse::ID, msgs[1][0].type()); |
+ ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[1][1].type()); |
- // TODO(mbelshe): |
- // Now that the async IO path is in place, the IO always completes on the |
- // initial call; so the cancel doesn't arrive until after we finished. |
- // This basically means the test doesn't work. |
-#if 0 |
int request_id; |
URLRequestStatus status; |
- // The message should be all data received with an error. |
- ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[1][2].type()); |
- |
void* iter = NULL; |
- ASSERT_TRUE(IPC::ReadParam(&msgs[1][2], &iter, &request_id)); |
- ASSERT_TRUE(IPC::ReadParam(&msgs[1][2], &iter, &status)); |
+ ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &request_id)); |
+ ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &status)); |
EXPECT_EQ(URLRequestStatus::CANCELED, status.status()); |
-#endif |
} |
// Tests CancelRequestsForProcess |
@@ -270,7 +270,7 @@ |
virtual bool Send(IPC::Message* msg) { |
// no messages should be received when the process has been canceled |
if (has_canceled_) |
- received_after_canceled_ ++; |
+ received_after_canceled_++; |
delete msg; |
return true; |
} |
@@ -283,6 +283,8 @@ |
ViewHostMsg_Resource_Request request = |
CreateResourceRequest("GET", URLRequestTestJob::test_url_1()); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
host_.BeginRequest(&test_receiver, GetCurrentProcess(), 0, MSG_ROUTING_NONE, |
1, request, NULL, NULL); |
KickOffRequest(); |
@@ -296,7 +298,7 @@ |
3, request, NULL, NULL); |
KickOffRequest(); |
- // TODO: mbelshe |
+ // TODO(mbelshe): |
// Now that the async IO path is in place, the IO always completes on the |
// initial call; so the requests have already completed. This basically |
// breaks the whole test. |
@@ -314,6 +316,7 @@ |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
EXPECT_EQ(0, host_.pending_requests()); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
// the test delegate should not have gotten any messages after being canceled |
ASSERT_EQ(0, test_receiver.received_after_canceled_); |
@@ -327,6 +330,8 @@ |
// Tests blocking and resuming requests. |
TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) { |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
host_.BlockRequestsForRenderView(0, 1); |
host_.BlockRequestsForRenderView(0, 2); |
host_.BlockRequestsForRenderView(0, 3); |
@@ -376,6 +381,8 @@ |
KickOffRequest(); |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
msgs.clear(); |
accum_.GetClassifiedMessages(&msgs); |
ASSERT_EQ(2, msgs.size()); |
@@ -385,6 +392,8 @@ |
// Tests blocking and canceling requests. |
TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) { |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
host_.BlockRequestsForRenderView(0, 1); |
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
@@ -409,6 +418,9 @@ |
host_.CancelBlockedRequestsForRenderView(0, 1); |
KickOffRequest(); |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
+ |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
msgs.clear(); |
accum_.GetClassifiedMessages(&msgs); |
ASSERT_EQ(0, msgs.size()); |
@@ -416,6 +428,9 @@ |
// Tests that blocked requests are canceled if their associated process dies. |
TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) { |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(1)); |
+ |
host_.BlockRequestsForRenderView(1, 0); |
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
@@ -429,6 +444,9 @@ |
// Flush all the pending requests. |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(1)); |
+ |
// Sort out all the messages we saw by request. |
ResourceIPCAccumulator::ClassifiedMessages msgs; |
accum_.GetClassifiedMessages(&msgs); |
@@ -461,3 +479,141 @@ |
// Flush all the pending requests. |
while (URLRequestTestJob::ProcessOnePendingMessage()); |
} |
+ |
+// Test the private helper method "CalculateApproximateMemoryCost()". |
+TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) { |
+ URLRequest req(GURL("http://www.google.com"), NULL); |
+ EXPECT_EQ(4425, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req)); |
+ |
+ // Add 9 bytes of referrer. |
+ req.set_referrer("123456789"); |
+ EXPECT_EQ(4434, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req)); |
+ |
+ // Add 33 bytes of upload content. |
+ std::string upload_content; |
+ upload_content.resize(33); |
+ std::fill(upload_content.begin(), upload_content.end(), 'x'); |
+ req.AppendBytesToUpload(upload_content.data(), upload_content.size()); |
+ |
+ // Since the upload throttling is disabled, this has no effect on the cost. |
+ EXPECT_EQ(4434, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req)); |
+ |
+ // Add a file upload -- should have no effect. |
+ req.AppendFileToUpload(L"does-not-exist.png"); |
+ EXPECT_EQ(4434, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req)); |
+} |
+ |
+// Test the private helper method "IncrementOutstandingRequestsMemoryCost()". |
+TEST_F(ResourceDispatcherHostTest, IncrementOutstandingRequestsMemoryCost) { |
+ ResourceDispatcherHost host(NULL); |
+ |
+ // Add some counts for render_process_host=7 |
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(7)); |
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(1, 7)); |
+ EXPECT_EQ(2, host.IncrementOutstandingRequestsMemoryCost(1, 7)); |
+ EXPECT_EQ(3, host.IncrementOutstandingRequestsMemoryCost(1, 7)); |
+ |
+ // Add some counts for render_process_host=3 |
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(3)); |
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(1, 3)); |
+ EXPECT_EQ(2, host.IncrementOutstandingRequestsMemoryCost(1, 3)); |
+ |
+ // Remove all the counts for render_process_host=7 |
+ EXPECT_EQ(3, host.GetOutstandingRequestsMemoryCost(7)); |
+ EXPECT_EQ(2, host.IncrementOutstandingRequestsMemoryCost(-1, 7)); |
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(-1, 7)); |
+ EXPECT_EQ(0, host.IncrementOutstandingRequestsMemoryCost(-1, 7)); |
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(7)); |
+ |
+ // Remove all the counts for render_process_host=3 |
+ EXPECT_EQ(2, host.GetOutstandingRequestsMemoryCost(3)); |
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(-1, 3)); |
+ EXPECT_EQ(0, host.IncrementOutstandingRequestsMemoryCost(-1, 3)); |
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(3)); |
+ |
+ // When an entry reaches 0, it should be deleted. |
+ EXPECT_TRUE(host.outstanding_requests_memory_cost_map_.end() == |
+ host.outstanding_requests_memory_cost_map_.find(7)); |
+ EXPECT_TRUE(host.outstanding_requests_memory_cost_map_.end() == |
+ host.outstanding_requests_memory_cost_map_.find(3)); |
+} |
+ |
+// Test that when too many requests are outstanding for a particular |
+// render_process_host_id, any subsequent request from it fails. |
+TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) { |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
+ // Expected cost of each request as measured by |
+ // ResourceDispatcherHost::CalculateApproximateMemoryCost(). |
+ int kMemoryCostOfTest2Req = |
+ ResourceDispatcherHost::kAvgBytesPerOutstandingRequest + |
+ std::string("GET").size() + |
+ URLRequestTestJob::test_url_2().spec().size(); |
+ |
+ // Tighten the bound on the ResourceDispatcherHost, to speed things up. |
+ int kMaxCostPerProcess = 440000; |
+ host_.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess); |
+ |
+ // Determine how many instance of test_url_2() we can request before |
+ // throttling kicks in. |
+ int kMaxRequests = kMaxCostPerProcess / kMemoryCostOfTest2Req; |
+ |
+ // Saturate the number of outstanding requests for process 0. |
+ for (int i = 0; i < kMaxRequests; ++i) |
+ MakeTestRequest(0, 0, i + 1, URLRequestTestJob::test_url_2()); |
+ |
+ // Issue two more requests for process 0 -- these should fail immediately. |
+ MakeTestRequest(0, 0, kMaxRequests + 1, URLRequestTestJob::test_url_2()); |
+ MakeTestRequest(0, 0, kMaxRequests + 2, URLRequestTestJob::test_url_2()); |
+ |
+ // Issue two requests for process 1 -- these should succeed since |
+ // it is just process 0 that is saturated. |
+ MakeTestRequest(1, 0, kMaxRequests + 3, URLRequestTestJob::test_url_2()); |
+ MakeTestRequest(1, 0, kMaxRequests + 4, URLRequestTestJob::test_url_2()); |
+ |
+ // Flush all the pending requests. |
+ while (URLRequestTestJob::ProcessOnePendingMessage()); |
+ MessageLoop::current()->RunAllPending(); |
+ |
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); |
+ |
+ // Sorts out all the messages we saw by request. |
+ ResourceIPCAccumulator::ClassifiedMessages msgs; |
+ accum_.GetClassifiedMessages(&msgs); |
+ |
+ // We issued (kMaxRequests + 4) total requests. |
+ ASSERT_EQ(kMaxRequests + 4, msgs.size()); |
+ |
+ // Check that the first kMaxRequests succeeded. |
+ for (int i = 0; i < kMaxRequests; ++i) |
+ CheckSuccessfulRequest(msgs[i], URLRequestTestJob::test_data_2()); |
+ |
+ // Check that the subsequent two requests (kMaxRequests + 1) and |
+ // (kMaxRequests + 2) were failed, since the per-process bound was reached. |
+ for (int i = 0; i < 2; ++i) { |
+ // Should have sent a single RequestComplete message. |
+ int index = kMaxRequests + i; |
+ EXPECT_EQ(1, msgs[index].size()); |
+ EXPECT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[index][0].type()); |
+ |
+ // The RequestComplete message should have had status |
+ // (CANCELLED, ERR_INSUFFICIENT_RESOURCES). |
+ int request_id; |
+ URLRequestStatus status; |
+ |
+ void* iter = NULL; |
+ EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &request_id)); |
+ EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &status)); |
+ |
+ EXPECT_EQ(index + 1, request_id); |
+ EXPECT_EQ(URLRequestStatus::CANCELED, status.status()); |
+ EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, status.os_error()); |
+ } |
+ |
+ // The final 2 requests should have succeeded. |
+ CheckSuccessfulRequest(msgs[kMaxRequests + 2], |
+ URLRequestTestJob::test_data_2()); |
+ CheckSuccessfulRequest(msgs[kMaxRequests + 3], |
+ URLRequestTestJob::test_data_2()); |
+} |
+ |